在分类术语中,FP中的monad是什么?
每当有人承诺“解释单子”时,我的兴趣就会激化,只有当所谓的“解释”是一个长长的清单时,才会被挫折所取代,这些清单是由一些副手所断言的“隐秘背后的数学理论”想法“在这一点上”太复杂了,无法解释“。
现在我要求相反。 我对类别理论有着坚实的把握,我不害怕图追逐,Yoneda的引理或派生的函数(事实上在单类和单数意义上的monad和adjunctions上)。
有人能给我一个关于函数式编程中monad的清晰简洁的定义吗? 例子越少越好:有时一个清晰的概念说明了超过一百个胆小的例子。 虽然我不挑剔,但Haskell会很好地作为演示语言。
作为对卡尔的回答的一种赞扬,哈斯克尔的一个Monad(理论上)是这样的:
class Monad m where
join :: m (m a) -> m a
return :: a -> m a
fmap :: (a -> b) -> m a -> m b
请注意,“绑定”( >>=
)可以定义为
x >>= f = join (fmap f x)
根据Haskell Wiki
C类中的monad是一个三元组(F:C→C,η:Id→F,μ:F∘F→F)
......有一些公理。 对于Haskell, fmap
, return
和join
分别与F,η和μ fmap
。 (Haskell中的fmap
定义了一个Functor)。 如果我没有弄错,Scala会将这些map
分别称为pure
和join
。 (Scala调用绑定“flatMap”)
这个问题有一些很好的答案:Monads作为附件
更重要的是,Derek Elkins在TMR#13中的“用分类理论计算Monads”一文应该有你想要的结构:http://www.haskell.org/wikiupload/8/85/TMR- Issue13.pdf
最后,也许这与你正在寻找的内容非常接近,你可以直接找到源并看看1988年到1991年间Moggi关于该主题的开创性论文:http://www.disi.unige.it/人/ MoggiE / publications.html
特别参见“计算和单子的概念”。
我自己肯定太浓缩/不精确:
与类别开始Hask
,其对象是Haskell的类型,且其态射的功能。 Hask
函数也是对象,产品也是。 所以Hask
是笛卡儿关闭的。 现在引入一个箭头,将Hask
每个对象映射到MHask
中对象子集的Hask
。 单元! 接着在每个箭头引入箭头映射Hask
到上的箭头MHask
。 这给了我们地图,并使MHask
成为共同的内部管理者。 现在介绍的箭头映射中的每个对象MHask
其从物体生成MHask
(通过单元),以在对象MHask
产生它。 加入! 从中可以看出, MHask
是一个monad(更精确的说是monoidal endofunctor)。
我确信有一个原因是为什么上述缺陷,这就是为什么我会真正指导你,如果你正在寻找形式主义,特别是对于莫吉论文。
好的,使用Haskell术语和示例...
在函数式编程中,monad是一种* -> *
类型数据类型的合成模式。
class Monad (m :: * -> *) where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(Haskell中的类比Haskell多,但这些是重要的部分。)
数据类型是一个monad,如果它可以在满足实现中的三个条件的同时实现该接口。 这些都是“单子法”,我将把它留给那些冗长的解释来解释。 我将这些规律归纳为“ (>>= return)
是一个身份函数, (>>=)
是关联的。” 即使它可以更精确地表达,它也不过如此。
这就是一个monad。 如果您可以在保留这些行为属性的同时实现该接口,则您有一个monad。
这个解释可能比你预期的要短。 这是因为monad接口真的很抽象。 令人难以置信的抽象层次是为什么许多不同的事物可以被模拟为单子的原因之一。
不太明显的是,尽管接口是抽象的,但它允许一般地建模任何控制流模式,而不管实际的monad实现如何。 这就是为什么Control.Monad
包GHC的base
库中有一个像组合程序when
, forever
等。而这就是为什么有能力明确抽象超过任何单子的实现是强大的,特别是从类型系统的支持。