2

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

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 dwhereg调用的结果bar以及baz它们的副作用。

有没有一种方法可以在g不将每个函数显式应用于结果的情况下进行构造foo?有点类似于(&&&)工作原理,或者(<*>)我想。

4

2 回答 2

4

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

g :: Monad m => m a -> m b
g foo = foo >>= bar .&. baz .&. qux
    where (.&.) = liftM2 (>>)
于 2013-07-27T16:23:05.740 回答
3

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

 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''' ....
于 2013-07-27T16:22:15.740 回答