對於Haskell的排序,你具備的功能>>=
和sequence
:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
sequence :: Monad m => [m a] -> m [a]
的>>=
或綁定功能需要一個單子行動,提取值從它並將它提供給一個函數,返回一個新的monadic動作。 sequence
函數獲取相同類型的monadic動作列表,並執行所有這些動作,彙總其結果並將其作爲單個動作進行封裝。
對於迭代你有mapM
和forM
(forM = flip mapM
)
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
的mapM
和forM
功能是用於將返回到各元件的動作列表中的一個功能,綜合這些結果作爲一個單一的動作。
對於選擇,我假設你的意思是條件,這些條件在Haskell中就像if-the-else表達式一樣實現。它們可以在monadic表達式中直接使用,它們可以在純表達式中使用。但是,您也可以使用某些monads來執行選擇或至少處理錯誤。最容易的是Maybe
monad:
data Maybe a = Nothing | Just a
instance Monad Maybe where
return a = Just a
(Just a) >>= f = f a
Nothing >>= f = Nothing
它有一個非常簡單的實現。實質上,如果您嘗試將Nothing
排序爲其他任何內容,則每次都會返回Nothing
。這給你短路故障的概念:
lookup :: Eq a => a -> [(a, b)] -> Maybe b
-- Looks up a value in a key-value association list
myFunc :: Int -> [(String, Int)] -> Maybe Int
myFunc mult assocList = do
i <- lookup "foo" assocList
j <- lookup "bar" assocList
return $ i * mult + j
這裏,如果"foo"
查找失敗,則myFunc
立即返回Nothing
。同樣,如果"bar"
的查找失敗,則myFunc
立即返回Nothing
。只有當兩個查找都成功時,myFunc
纔會進行任何計算。這提供了一種「錯誤處理」。還有一個類似的單子Either a
data Either a b = Left a | Right b
instance Monad (Either a) where
return a = Right a
(Right a) >>= f = f a
(Left a) >>= f = Left a
的作品大同小異,不同的是「失敗」的值可以隨身攜帶一些方面,如字符串錯誤消息或計算在故障點的狀態。
「>> =」是否真的能夠保證排序或僅僅是最常見單子的行爲? – kqr
@kqr它不保證評估的順序,如果這是你問的問題。原因是評估的順序取決於'(>> =)'的定義,而不是所有的實現都是在第二個參數之前評估第一個參數。 –
@kqr它不能保證排序,但它是允許我們使用'do'符號的函數,這就是我將問題解釋爲問的問題。由於bind基本上爲do語句中的每個動作定義了(隱含的)分號,因此它給了我們一種爲特定代碼塊定義控制流方面的方法。 – bheklilr