题
从 一个温和的介绍Haskell, 有以下单的法律。任何人都可以直观地解释他们是什么意思?
return a >>= k = k a
m >>= return = m
xs >>= return . f = fmap f xs
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
这是我试图解释:
我们期望回报的功能包裹
a
因此,它的元性是微不足道的。当我们结合到一个功能,有没有一元的影响,它应该只是传递a
的功能。解开输出
m
传递到return
这rewraps。这一元性的保持相同。所以它是相同的原始单.解开价值传递给
f
然后重新压缩.这一元性的保持相同。这是行为的期望,当我们改变一个功能正常进入一个一元的职能。我没有解释这项法律。这并说,单必须是"几乎的关联"。
解决方案
你的描述似乎很好。通常人们说话的三单法律,你已经为1、2、和4。你的第三个法略有不同,我将得到以后。
三单法律,我发现它很容易得到一个直观地了解他们是什么意思,当他们重新写入使用Kleisli组成:
-- defined in Control.Monad
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
mf >=> n = \x -> mf x >>= n
现在,法律可以写为:
1) return >=> mf = mf -- left identity
2) mf >=> return = mf -- right identity
4) (f >=> g) >=> h = f >=> (g >=> h) -- associativity
1)留身份法返回的一个价值不变的价值和没有做任何事情的单.
2)正确的身份法返回的一个价值不变的价值和没有做任何事情的单.
4)结合性-元组成的关联(我喜欢KennyTM的答案)
两个身份法律基本上说同样的事情,但它们都是必要的,因为 return
应该有身份的行为在两个侧面结合经营者。
现在的第三项法律。这项法律本质上说,两者的函的实例和你单实例的行为方式相同时提升功能进入单,也没有任何东西一元.如果我没有记错的话,这种情况下,当一个单遵守其他三项法律和函子实例的遵守函的法律,则该声明将永远是真实的。
很多这种来自 Haskell Wiki.的 Typeclassopedia 是一个很好的参考。
其他提示
没有分歧与其他的答案,但它可能有助于思考的单的法律如实描述 两个 集的性质。作为约翰说,第三定律说是稍有不同,但这里的别人如何可以拆除:
功能结合到一个单撰写就像普通的职能。
正如在约翰回答,是什么叫Kleisli箭头用一个单一功能的类型 a -> m b
.想想 return
作为 id
和 (<=<)
作为 (.)
, 和单的法律翻译:
id . f
相当于f
f . id
相当于f
(f . g) . h
相当于f . (g . h)
序列的一元的追加影响喜欢的名单。
大部分,可以认为额外元结构作为一系列额外的行为相关的元价值;例如 Maybe
被"放弃"为 Nothing
和"继续"于 Just
.合并两个单子的行动,然后基本上将序列的行为他们举行。
在这个意义上说, return
又是一个身份--空行动,类似于一个空的行为列表--和 (>=>)
是串联。因此,单的法律翻译:
[] ++ xs
相当于xs
xs ++ []
相当于xs
(xs ++ ys) ++ zs
相当于xs ++ (ys ++ zs)
这三个法律描述了一个可笑的共同模式,其Haskell不幸的是,不能完全表达的完全普遍性。如果你有兴趣, Control.Category
给出了一个概括的"事情,看起来像功能组成",同时 Data.Monoid
概括后一种情况下,那里没有类型参数的参与。
在条款 do
符号,第4条意味着我们可以添加一个额外的 do
块组序列的单子操作。
do do
y <- do
x <- m x <- m
y <- k x <=> k x
h y h y
这一功能允许返回元价值的正常工作。
第三定律说,"返回"只有一个包裹值和没有别的。所以你可以消除的"返回"的呼吁没有变化的语义学。
最后一个法是关联性对于结合。这意味着你需要的东西,如:
do
x <- foo
bar x
z <- baz
并把它变成
do
do
x <- foo
bar x
z <- baz
而意思又不改变。当然你不会做到这一点,但是你可能想要把内"做"的规定在一个"如果"的发言,并希望它意味着同时将"如果"是真实的。
有时候单元的不完全按照这些法律,特别是当某些种类的底价值时发生。那好吧只要它的记录是"在道义上正确的"(即法律都遵循非底值,或结果被认为等同于某些其他方式)。