風格上這是非常好的。在現實世界中,我希望這個符號,而不是你給了一個60%的機會:
C x c >>= f = C (value $ f x) (c + 1)
但是,這是如此輕微它是幾乎不值得一提。
在更嚴重的注意,不是文體但語義:這不是一個單子。事實上,它違反了所有三項單子法。
(1) return x >>= f = f x
(2) m >>= return = m
(3) m >>= (f >=> g) = (m >>= f) >>= g
(凡(>=>)
被定義爲f >=> g = \x -> f x >>= g
,如果(>>=)
被認爲是一個「應用程序」操作,然後(>=>)
是相應組成運營商。我喜歡,因爲它帶出了第三定律的陳述使用該運營商的第三定律這意味着:結合性)
隨着這些計算:
(1):
return 0 >>= return
= C 0 0 >>= return
= C (value $ return 0) 1
= C 0 1
Not equal to return 0 = C 0 0
(2):
C 0 0 >>= return
= C (value $ return 0) 1
= C 0 1
Not equal to C 0 0
(3)
C 0 0 >>= (return >=> return)
= C (value $ (return >=> return) 0) 1
= C (value $ return 0 >>= return) 1
= C (value $ C 0 1) 1
= C 0 1
Is not equal to:
(C 0 0 >>= return) >>= return
= C (value $ return 0) 1 >>= return
= C 0 1 >>= return
= C (value $ return 0) 2
= C 0 2
這不只是在執行一個錯誤 - 沒有單子是 「計算綁定數量」。它必須違反法律(1)和(2)。但是,您違反法律(3)的事實是實施錯誤。
麻煩的是,(>>=)
定義中的f
可能會返回一個具有多個綁定的操作,而您忽略了該操作。您需要添加綁定數量從左邊和右邊的參數:
C x c >>= f = C y (c+c'+1)
where
C y c' = f x
這將正確計算的綁定數量,並且將滿足第三定律,這是關聯性法律。它不會滿足其他兩個。但是,如果您從此定義中刪除+1
,那麼做的會得到一個真正的monad,這相當於+
monoid上的Writer
monad。這基本上將所有子計算的結果加在一起。你可以用這個來計算約會的數量,只是不綁定 - 綁定是非常特殊的數量。但是,例如:
tick :: C()
tick = C() 1
然後C
將計算的發生在計算tick
S上的號碼。
事實上,你可以替換Int
與任何類型和(+)
任何關聯運營商,並得到一個單子。一般來說,這就是monad的一個Writer
。如果操作員不是聯想的,那麼這會違反第三條法則(你能明白爲什麼?)。
這不是我所期待的,但肯定是我需要的。爲什麼如果操作者不是聯想的,第三定律被打破:因爲第三定律是結合的聯合性。如果綁定「做」了某些不相關的東西(我不能給出「確定」的確切定義),那麼它本身也不可能是關聯的。是對的嗎? – abesto 2011-01-22 01:12:32