从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
我尝试为Traversable
定义Product f g a
实例:
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)
?请解释上面的实际类型。
答案 0 :(得分:4)
是的。你有
traverse :: (a -> h b) -> f a -> h (f b)
traverse fn fa :: h (f b) -- and,
traverse :: (a -> h b) -> g a -> h (g b)
traverse fn ga :: h (g b)
因此
Product (traverse fn fa) (traverse fn ga) :: Product h h (f b)
(h (f b)) (h (g b))
强制使用等效项f b ~ g b
即f ~ g
,因为Product p q t
被定义为
Product (p t ) (q t )
------------------------------------------
p ~ h t ~ f b q ~ h t ~ g b
因此,将Product
应用于两个traverse
的结果并没有成功。
但是两者的类型分别为h (f b)
和h (g b)
,并且h
是一个Applicative,我们试图创建类型为h (Product f g b)
并带有 在h
的内部键入,所以只要我们能
h (f b) h (g b) h r h s
--------------------------- ----------------------
h (Combined (f b) (g b)) h (Combined r s)
,事实上,由于两个b
是相同的,
---------------------------
h (Combined f g b )
因此,我们想从foo :: r -> s -> t
中获取bar :: h r -> h s -> h t
...如果只有such a function ...
baz :: (Applicative h) => (r -> s -> t) -> (h r -> h s -> h t)
...,答案是liftA2 Product (traverse fn fa) (traverse fn ga)
,将数据构造函数Product
应用于两个遍历的内部结果“ in” (“ inside” ,”(位于“ ”的幕后)
h r h s
r -> s -> t
------------------------
h t