有几个基本的惯用combinators反复弹出,并重新实现了各种高级概念和库,但实质上非常简单。名称可能会有所不同,而在其他方面有些是可实现的:
fork (f,g) x = (f x, g x) -- == (f &&& g)
prod (f,g) x = (f $ fst x, g $ snd x) -- == (f *** g)
pmap f (x,y) = (f x, f y) -- == (f *** f)
dup x = (x,x)
等。当然uncurry f (x,y) == f x y
中被使用了很多与这些了。
&&&
和***
在Control.Arrow
定义,以及first
和second
。然后prod (f,id) == first f
,prod(id,g) == second g
等等,等等
所以你foobar
变得
foobar = (\(a,b)->[a,b]) . fork (id,reverse)
= (\(a,b)->[a,b]) . (id &&& reverse)
= (\(a,b)->[a,b]) . (id *** reverse) . dup
= join $ curry ((\(a,b)->[a,b]) . second reverse)
对于您还需要导入Control.Monad
和Control.Monad.Instances
最后一个。另见this question。
后期编辑:此外,使用Control.Applicative
由ertes回答暗示,
= (:) <*> ((:[]) . reverse)
只有当你确定与约束。这不适用于所有用途。 – 2012-07-29 14:43:20
@ ThomasM.DuBuisson:什么约束? – 2012-08-09 14:30:44
@BenMillwood我指的是typeclass约束。 JohnL的答案是'a - > [a]'类型。这个答案虽然很好干净,但是类型为Monad(( - > a)=> a - > [a]' – 2012-08-09 15:57:47