Monad如何符合功能的组成

时间:2014-11-17 19:18:41

标签: haskell

我知道这些功能都与构图有关。例如,如果我有一个从A到B的箭头和一个从B到C的箭头,则组合意味着我还有一个从A到C的箭头。

但对于(>>=),其类型为Monad m => m a -> (a -> m b) -> m b。为什么m a等于a

我想知道为什么不Monad m => m a -> (m a -> m b) -> m b?这更有意义吗?

4 个答案:

答案 0 :(得分:6)

尝试自己实现该功能,你会发现它没用:

func :: Monad m => m a -> (m a -> m b) -> m b
func x f = f x

所以你基本上建议的是将值应用于函数。我认为我们不需要特殊的功能。 :-) >>=的重点是它执行第一个参数的副作用,然后将结果值传递给函数。

答案 1 :(得分:6)

@Sibi的回答是正确的,将monad定义为第二个签名是没有意义或有用的。但是关于你关于函数组成和monadic组合之间关系的问题,还有另一种看待运算符的方法。

Monads有一堆替代结构,相当于绑定/返回公式。其中一个是运算符(<=<),称为Kleisli组合运算符,它以与结构相似的方式组成monadic运算。

箭头:

Functions          : a -> b
Monadic operations : a -> m b

成分:

-- Function composition
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> g (f x)

-- Monad composition
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
f <=< g ≡ \x -> g x >>= f 

Gabriel Gonzalez写了一篇关于这种模式的好文章:http://www.haskellforall.com/2012/08/the-category-design-pattern.html

答案 2 :(得分:5)

>>=与组合不对应,它对应于(翻转)应用程序。翻转版本=<<清楚地说明了这一点:

($)   ::              (a ->   b) ->   a ->   b
(=<<) :: (Monad m) => (a -> m b) -> m a -> m b

($)采用一元函数并将其应用于值,给出一个值; =<<采取一元行动并将其应用于违规行为的结果,并采取行动。

<=< >=>相对应的运算符为Control.Monad(.) :: (b -> c) -> (a -> b) -> a -> c (<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c

(.)

<=<组成两个一元函数,给出一元函数; {{1}}组成两个一元行动,给予一元行动。

答案 3 :(得分:1)

如果您重新排序类型签名,那么对您来说会更有意义....

modify成为(&gt;&gt; =)翻转顺序

modify::Monad m => (a -> m b) -> m a -> m b

或添加隐含的括号

modify::Monad m => (a -> m b) -> (m a -> m b)

现在很明显发生了什么......我们得到了一个“不平衡”的功能,不能放在固定数据类型的管道中,并将其转换为可以实现的功能......这些功能更好处理,因为你可以随意添加和删除它们,应用N次,甚至重新排序。 (好吧,对于a=b, at least

模式很常见....例如,a->m b可能是一个带val的函数,可能会也可能不会返回值或错误。