是否有一个组合器将多个函数应用于Haskell中的单个值?

时间:2013-07-27 15:28:17

标签: haskell pointfree

例如,假设我有以下功能:

foo :: Monad f => f a
bar :: Monad f => a -> f b
baz :: Monad f => a -> f c
qux :: Monad f => a -> f d

我只想返回qux的结果,例如g :: Monad f => f a -> f d, 其中g可能会调用barbaz的副作用。

有没有办法构建g而不明确将每个函数应用于foo的结果?与(&&&)的工作方式有些相似,或者我认为是(<*>)

2 个答案:

答案 0 :(得分:4)

这是使用Monad ((->) r)实例的可能解决方案。这很好用,并且可以扩展到必要的功能应用程序。

g :: Monad m => m a -> m b
g foo = foo >>= bar .&. baz .&. qux
    where (.&.) = liftM2 (>>)

答案 1 :(得分:3)

我假设a b cd实际上不应该是类型变量,而是你的意思更像

 data A
 data B
 data C
 data D

因为否则你要求的是forall a b. a -> b类型的函数,这是不可能有意义地创建的。

k = Kleisli
a &^& b = a &&& b >>> arr snd
g = runKleisli $ k bar &^& k baz &^& k quux

是一种简单的方法。它使用围绕Monad的kleisli箭头将其抬起到箭头之地。我不知道有任何漂亮的组合器以预定义的方式完成&^&,但定义起来非常简单。

好消息是,这可以简单地缩放并且是无点的

 g = runKleisli $ k f &^& k f' &^& k f'' &^& k f''' ....