[英]First experience with monads (Haskell)
對於這個主題不清楚,我深表歉意。 我正在初學者學習Haskell 99,並且在我的67A解決方案中第一次遇到了monad的概念。 我苦苦掙扎的問題的一部分是定義一個函數stringToTree
,該函數將a(b,c)
類a(b,c)
序列轉換為Tree
: Branch a (Branch b Empty Empty) (Branch c Empty Empty)
。
我已經嘗試了幾種有關monad的“軟”介紹,但與其他許多例子一樣都失敗了。 我希望通過了解此解決方案最終能帶領我進入室內,因此我決定在此進行嘗試。
stringToTree :: (Monad m) => String -> m (Tree Char)
是什么? 為了使這個問題自成一體,我從那里復制了代碼 stringToTree :: (Monad m) => String -> m (Tree Char)
stringToTree "" = return Empty
stringToTree [x] = return $ Branch x Empty Empty
stringToTree str = tfs str >>= \ ("", t) -> return t
where tfs a@(x:xs) | x == ',' || x == ')' = return (a, Empty)
tfs (x:y:xs)
| y == ',' || y == ')' = return (y:xs, Branch x Empty Empty)
| y == '(' = do (',':xs', l) <- tfs xs
(')':xs'', r) <- tfs xs'
return $ (xs'', Branch x l r)
tfs _ = fail "bad parse"
monad
在這里有用? 我希望看到單子如何在定義此功能的同時大幅度減少困難,當然只有在了解了這一點之后。 簡而言之,定義使呼叫者可以選擇要使用的單聲道。 這使我們可以自定義處理失敗的方式。 例如,我們可以使用Maybe
:
>>> stringToTree "" :: Maybe (Tree Char)
Just Empty
>>> stringToTree "9 +" :: Maybe (Tree Char)
Nothing
或[]
:
>>> stringToTree "" :: [Tree Char]
[Empty]
>>> stringToTree "9 +" :: [Tree Char]
[]
該代碼本身不假設使用哪個 monad。 它僅使用>>=
, return
,並且fail
處理遞歸調用的結果。
鍵入String -> Tree Char
表示失敗根本不會發生。 每個字符串都必須產生一個有效的Tree Char
值(否則我們會引發運行時錯誤,這是您在Haskell中應避免的事情)。
但是請注意,並非所有monad都提供了避免運行時錯誤的fail
定義。
>>> stringToTree "" :: Either () (Tree Char)
Right Empty
>>> stringToTree "9 +" :: Either () (Tree Char)
*** Exception: bad parse
為什么monad有用? 一些更廣泛的背景。
Monad是傳統上由不同語言機制處理的幾件事的統一 。 其中有
排序(例如在IO或狀態下)
非確定性(例如清單monad)
失敗和異常(例如Maybe)
保存和恢復計算(將來會遇到的Cont monad)
原子交易(STM monad)
解析(Parsec及其親屬)
所謂“統一”,是指牛頓將地球上和天空中的事物的物理定律統一起來,或者將麥克斯韋將電磁力統一到電磁場中時所做的事情。 它是一種更深層的基礎理論,將以上所有內容作為特殊情況進行了介紹,並展示了如何沿着相同思路創造新事物。
在monad中,“ bind”函數的類型(>>=)
是理論中的中心方程; 它描述了如何將計算的一個步驟以菊花鏈方式鏈接到下一個步驟。 return
是原始的空步驟。 這是您在Haskell中習慣的; 一切都有某種零或空或身份值。 fail
是不起作用的步驟,部分功能需要該步驟(如@chepner在其他評論中所述)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.