traverse
类中的sequenceA
和Traversable
函数必须满足以下“自然性”定律:
t . traverse f == traverse (t . f)
t . sequenceA == sequenceA . fmap t
对于每一个'应用转型't
。但它是什么?
它似乎对instance Traversable []
t = tail
不起作用:
Prelude> tail . sequenceA $ [[1],[2,3]]
[[1,3]]
Prelude> sequenceA . fmap tail $ [[1],[2,3]]
[]
也不是t = join (++)
(重复列表两次):
Prelude Control.Monad> join (++) . sequenceA $ [[1],[2,3]]
[[1,2],[1,3],[1,2],[1,3]]
Prelude Control.Monad> sequenceA . fmap (join (++)) $ [[1],[2,3]]
[[1,2],[1,3],[1,2],[1,3],[1,2],[1,3],[1,2],[1,3]]
那么对于什么t
他们满意?
Data.Traversable的Hackage页面定义了一个应用程序转换,如下所示。
[A] n应用转换是一种功能
t :: (Applicative f, Applicative g) => f a -> g a
保留适用的操作,即
t (pure x) = pure x t (x <*> y) = t x <*> t y
最简单的例子是身份功能。 id
是一个应用转型。列表的一个更具体的例子是reverse
。
reverse (pure x) = reverse [x] = [x] = pure x
-- (the (<*>) law is more difficult to show)
你可以在GHCi中验证你引用的法律确实适用于reverse
。
Prelude> reverse . sequenceA $ [[1], [2,3]]
[[1,3],[1,2]]
Prelude> sequenceA . fmap reverse $ [[1], [2,3]]
[[1,3],[1,2]]
资料来源:Data.Traversable