箭头比haskell中的常规函数有什么优势。他们可以做什么功能不能。函数可以使用fmap映射结构。
答案 0 :(得分:6)
更广泛地说,箭头可以让你摆脱 Hask ,并进入其他类别进行探索。 Kleisli类别可能是最熟悉的Haskellers,其次是Cokleisli。这些是自然的"扩展" Hask :在结果或参数周围添加一个endofunctor,然后再次获得一个类别
Kleisli
:仿函数是一个monad,所以id ≅ return :: a -> m a
(.) ≅ (<=<) :: (b->m c) -> (a->m b) -> a->m c
CoKleisli
:仿函数是一个comonad,所以id ≅ coreturn :: m a -> a
和
(.) :: (m b->c) -> (m a->b) -> m a->c
(为此你还不需要Arrow
,只有Category
。但是一般类别并不是很有趣,你通常想要 monoidal 或甚至笛卡儿关闭的类别,这是Arrow
大致瞄准的目标。)
但确实有很多other categories。大多数与 Hask 无关,并且无法用标准Arrow
类表达,主要是因为对象具有并非每个Haskell类型都满足的特殊属性。实际上,如果添加约束对象类型的功能,the possibilities immediately become much wider。但即使你坚持使用标准类,也许只是在->
中,使用箭头自然的无点组合风格通常会非常好,简洁,并开辟了思考转换的新方法。
答案 1 :(得分:3)
函数只是箭头的一个实例,就像问“为什么使用monad而不仅仅是Maybe
”。
你可以用箭头做任何事情当然可以用函数来完成,因为Arrow (->)
实例只能讨论一小部分函数,即Arrow
类型类中的函数。但是,箭头比普通函数具有更多实例,因此我们可以使用ssame函数来处理更复杂的类型。
箭头很好,因为它们可以拥有比仅仅函数更多的结构,当只用fmap
遍历时,我们无法累积效果,比monad更具表现力!考虑Kleisli箭头,
newtype Kleisli m a b = Kleisli {runKleisli :: a -> m b}
当m
是monad时,这会形成一个箭头。所以每个Monad
形成一个箭头,因此我们可以通过无缝地组合a -> m b
来建立monadic计算,并做各种有用的事情。一些XML库使用箭头来抽象从元素到其子元素的函数,并使用它来遍历文档。其他解析器使用箭头(它们的最初目的)虽然现在这似乎不再受Applicative
的支持。
你希望注意到的一点是箭头更通用,当我们只谈论箭头时,我们避免复制我们需要编写的所有代码来使用我们的解析器,xml scraper和monadic函数做一些事情!
与选择Monad
而不是Maybe
一样,我们失去了一些权力,因为我们不再能够制作特定的语句,但我们会得到更多通用代码作为回报。