2014-01-13 87 views
0

爲了更好地理解monad,我試圖寫我自己的。我從一些非一元代碼開始,可以使用一些幫助將它翻譯成單元。Haskell:翻譯爲Monad

這個人爲的例子的基本思想:對於計算的每個整數結果,我想跟蹤該整數是偶數還是奇數。例如,在4 + 5 = 9中,我們可能會返回(9, Odd)。我想用>>=連鎖/組合計算。例如:

return 1 >>= (+2) >>= (+5) >>= (+7) =result=> (15, Odd) 

現在,我有以下的非單一產品代碼:

data Quality = Odd | Even deriving Show 

qual :: Integer -> Quality 
qual x = case odd x of 
      True -> Odd 
      _ -> Even 

type Qualifier = (Integer, Quality) 

mkQ :: Integer -> Qualifier 
mkQ x = (x, qual x) 

plusQ :: Qualifier -> Qualifier -> Qualifier 
plusQ (x, _) (y, _) = (x+y, qual (x+y)) 

chain = plusQ (mkQ 7) . plusQ (mkQ 5) . plusQ (mkQ 2) 

有什麼辦法我能翻譯上面的代碼放到一個單子?我應該尋找哪些模式以及它們的常用翻譯模式是什麼?

非常感謝提前!

+2

這不容易承認一元翻譯。 Monads通過類型進行參數化,對任何類型都有意義。 Yor計算只對內部人員有意義。 –

+1

看起來你正在試圖模擬狀態轉換/動作,在這種情況下,你的狀態就是「質量」。你會想看看[** State Monad **](http://learnyouahaskell.com/for-a-few-monads-more),其中你的狀態monad是由「Quality」和你的操作參數化的, (+1)'會變成狀態行爲。 – aaronlevin

+0

@ n.m。好點,也是我開始看到和想知道的。什麼可能是一個簡單的,通用的過程的更好的例子,適合這樣的練習? –

回答

0

很多從這個學習的。非常感謝評論員和你的時間和指導的答案!

總結:

解決方案:作爲@牛米。和其他人評論說,這個例子沒有很好的monad翻譯,因爲我的原始模型不是類型通用的。 Monads最適合類型通用計算模式。給出的好例子包括用於計算失敗的Maybe monad和用於通過計算鏈存儲和攜帶附件狀態信息的State monad。

作爲備用解決方案,@GabrielGonzalez提供了一個使用類型實例化的出色解決方案。這保持了我原始模型的固有類型特異性,但擴大了它的界面以支持更多類型的類接口並清理功能性交互。

下一個步驟:由於@weirdcanada和別人推薦的,我想我會去與State單子玩,看我怎麼可以把它應用到這個特殊的例子。然後,我可以試着用自己定義的Maybe作爲@ n.m。推薦的。

再次,非常感謝那些評論和迴應!

3

我想你真正想要的是一個Qualified例如Num

data Qualified = Qualified { isEven :: Bool, value :: Integer } 

instance Num Qualified where 
    (Qualified e1 n1) + (Qualified e2 n2) = Qualified e (n1 + n2) 
     where 
     e = (e1 && e2) || (not e1 && not e2) 

    (Qualified e1 n1) * (Qualified e2 n2) = Qualified (e1 || e2) (n1 * n2) 

    abs (Qualified e n) = Qualified e (abs n) 

    signum (Qualified e n) = Qualified e (signum n) 

    fromInteger n = Qualified (even n) n 

這使您可以直接操縱使用數學運算符Qualified號:

>>> let a = fromInteger 3 :: Qualified 
>>> let b = fromInteger 4 :: Qualified 
>>> a 
Qualified {isEven = False, value = 3} 
>>> b 
Qualified {isEven = True, value = 4} 
>>> a + b 
Qualified {isEven = False, value = 7} 
>>> a * b 
Qualified {isEven = True, value = 12} 
+1

OP可能想要一個'Num'實例,但我認爲更廣泛的目標是OP想要學習和理解monads。 – aaronlevin

+3

我擔心,在這個特定問題的背景下教授monad會造成更多的傷害而不是好處。 –

+0

@GabrielGonzalez很好的關注,並擔心承認。什麼可能是一個更好的簡單類型的monad,可以從頭開始編寫,以獲得更好的單子感? –