使用记录访问器定义 Applicative 的 <*> 时出错:无法构造无限类型:t ~ t -> t1
Error on defining Applicative's <*> with record accessors: cannot construct the infinite type: t ~ t -> t1
我有以下代码:
{-# LANGUAGE DeriveFunctor #-}
data Foo a = Foo { field1 :: a, field2 :: a} deriving (Functor)
instance Applicative Foo where
pure a = Foo a a
f <*> a = Foo (r field1) (r field2)
where r g = g f $ g a
我在 GHCi 中遇到以下错误:
help.hs:8:23: error:
• Occurs check: cannot construct the infinite type: t ~ t -> t1
• In the second argument of ‘($)’, namely ‘g a’
In the expression: g f $ g a
In an equation for ‘r’: r g = g f $ g a
• Relevant bindings include
g :: Foo (a -> b) -> t -> t1 (bound at help.hs:8:13)
r :: (Foo (a -> b) -> t -> t1) -> t1 (bound at help.hs:8:11)
help.hs:8:25: error:
• Couldn't match type ‘a’ with ‘a -> b’
‘a’ is a rigid type variable bound by
the type signature for:
(<*>) :: forall a b. Foo (a -> b) -> Foo a -> Foo b
at help.hs:7:5
Expected type: Foo (a -> b)
Actual type: Foo a
• In the first argument of ‘g’, namely ‘a’
In the second argument of ‘($)’, namely ‘g a’
In the expression: g f $ g a
• Relevant bindings include
g :: Foo (a -> b) -> t -> t1 (bound at help.hs:8:13)
r :: (Foo (a -> b) -> t -> t1) -> t1 (bound at help.hs:8:11)
a :: Foo a (bound at help.hs:7:9)
f :: Foo (a -> b) (bound at help.hs:7:3)
(<*>) :: Foo (a -> b) -> Foo a -> Foo b (bound at help.hs:7:3)
我如何实现 Foo 的这个应用仿函数实例以便它编译?
定义
r g = g f $ g a
要求g
是一个多态函数 -- GHC 无法推断出如此复杂的类型。
如果你真的想让你的代码编译,你需要在你的类型中更加明确:
{-# LANGUAGE ScopedTypeVariables, DeriveFunctor, InstanceSigs, Rank2Types #-}
instance Applicative Foo where
pure a = Foo a a
(<*>) :: forall a b. Foo (a->b) -> Foo a -> Foo b
f <*> a = Foo (r field1) (r field2)
where
r :: (forall t. Foo t -> t) -> b
r g = g f $ g a
或者,可以使用一种更直接的方法:
instance Applicative Foo where
pure a = Foo a a
(Foo f1 f2) <*> (Foo a1 a2) = Foo (f1 a1) (f2 a2)
我有以下代码:
{-# LANGUAGE DeriveFunctor #-}
data Foo a = Foo { field1 :: a, field2 :: a} deriving (Functor)
instance Applicative Foo where
pure a = Foo a a
f <*> a = Foo (r field1) (r field2)
where r g = g f $ g a
我在 GHCi 中遇到以下错误:
help.hs:8:23: error:
• Occurs check: cannot construct the infinite type: t ~ t -> t1
• In the second argument of ‘($)’, namely ‘g a’
In the expression: g f $ g a
In an equation for ‘r’: r g = g f $ g a
• Relevant bindings include
g :: Foo (a -> b) -> t -> t1 (bound at help.hs:8:13)
r :: (Foo (a -> b) -> t -> t1) -> t1 (bound at help.hs:8:11)
help.hs:8:25: error:
• Couldn't match type ‘a’ with ‘a -> b’
‘a’ is a rigid type variable bound by
the type signature for:
(<*>) :: forall a b. Foo (a -> b) -> Foo a -> Foo b
at help.hs:7:5
Expected type: Foo (a -> b)
Actual type: Foo a
• In the first argument of ‘g’, namely ‘a’
In the second argument of ‘($)’, namely ‘g a’
In the expression: g f $ g a
• Relevant bindings include
g :: Foo (a -> b) -> t -> t1 (bound at help.hs:8:13)
r :: (Foo (a -> b) -> t -> t1) -> t1 (bound at help.hs:8:11)
a :: Foo a (bound at help.hs:7:9)
f :: Foo (a -> b) (bound at help.hs:7:3)
(<*>) :: Foo (a -> b) -> Foo a -> Foo b (bound at help.hs:7:3)
我如何实现 Foo 的这个应用仿函数实例以便它编译?
定义
r g = g f $ g a
要求g
是一个多态函数 -- GHC 无法推断出如此复杂的类型。
如果你真的想让你的代码编译,你需要在你的类型中更加明确:
{-# LANGUAGE ScopedTypeVariables, DeriveFunctor, InstanceSigs, Rank2Types #-}
instance Applicative Foo where
pure a = Foo a a
(<*>) :: forall a b. Foo (a->b) -> Foo a -> Foo b
f <*> a = Foo (r field1) (r field2)
where
r :: (forall t. Foo t -> t) -> b
r g = g f $ g a
或者,可以使用一种更直接的方法:
instance Applicative Foo where
pure a = Foo a a
(Foo f1 f2) <*> (Foo a1 a2) = Foo (f1 a1) (f2 a2)