【发布时间】:2019-02-18 17:39:45
【问题描述】:
鉴于fp-course的以下内容:
data Product f g a =
Product (f a) (g a)
class Functor f where
-- Pronounced, eff-map.
(<$>) ::
(a -> b)
-> f a
-> f b
class Functor f => Applicative f where
pure ::
a -> f a
(<*>) ::
f (a -> b)
-> f a
-> f b
我试图为Product f g a 定义Traversable 实例:
instance (Traversable f, Traversable g) =>
Traversable (Product f g) where
traverse ::
Applicative h =>
(a -> h b)
-> Product f g a
-> h (Product f g b)
traverse fn (Product fa ga) = Product (traverse fn fa) (traverse fn ga)
编译器显示错误:
src/Course/Traversable.hs:106:33: error:
• Occurs check: cannot construct the infinite type: h ~ Product h h
Expected type: h (Product f g b)
Actual type: Product h h (f b)
我明白我的定义是怎么错的,但我不明白实际的类型是Product h h (f b)。
拆开Product (traverse fn fa) (traverse fn ga)的类型,我相信是:
Product (h (f b)) (h (g b))
因为traverse的签名是Applicative f => (a -> f b) -> t a -> f (t b)。
g 根据Product h h (f b) 的实际类型去哪里?请解释一下上面的实际类型。
【问题讨论】:
-
您可能会发现使用
liftA2(Applicative导出的Applicative方法)比<$>和<*>更容易定义这个特定实例。我还强烈建议使用打字孔来解决问题:traverse fn (Product fa ga) = _ (traverse fn fa) (traverse fn ga)会给你一个错误消息,显示你已经得到了什么以及你仍然需要产生什么。 -
谢谢,@dfeuer!我在 fp-course 上使用过很多类型孔!
标签: haskell