我對Haskell來說真的很新,所以這可能是一個愚蠢的問題。我有一個功能在Haskell中循環Monads
foo :: Int -> IO()
其結果會打印出一些有用的信息。現在我想要做到這一點:
do
foo 0
foo 1
foo 0
foo 2
foo 3
我該怎麼寫這個循環?我的問題是'連接'Monads,這是由do語句自動完成的...
謝謝你的幫忙!
我對Haskell來說真的很新,所以這可能是一個愚蠢的問題。我有一個功能在Haskell中循環Monads
foo :: Int -> IO()
其結果會打印出一些有用的信息。現在我想要做到這一點:
do
foo 0
foo 1
foo 0
foo 2
foo 3
我該怎麼寫這個循環?我的問題是'連接'Monads,這是由do語句自動完成的...
謝謝你的幫忙!
mapM_ foo [0,1,0,2,3]
會做的伎倆。
或許更重要的是「一個人怎麼知道?」 Hoogle是一個奇妙的工具。您想要將簽名爲Int -> IO()
的函數應用於一堆Int
以獲得新的IO操作。你正在尋找的東西將因此有簽名(Int -> IO()) -> [Int] -> IO()
,所以我們去和ask Hoogle for functions with that signature。第二個結果是mapM_
,其簽名是
Monad m => (a -> m b) -> [a] -> m()
權,其實這樣mapM_
與任何單子(不只是IO
)和任何類型(不只是Int
)的作品。當你想到它時,這根本就不奇怪。
你想要mapM_
組合子,它映射函數返回一個列表一個單子值,並且使用的是綁定運營商的測序結果:
>> let foo n = putStrLn (show n ++ "!")
>> mapM_ foo [0,1,0,2,3]
0!
1!
0!
2!
3!
有時,人們喜歡用翻轉版本
for :: Monad m => [a] -> (a -> m b) -> m()
for = flip mapM_
這看起來更像是勢在必行代碼:
>> for [1..5] $ \n ->
putStrLn ("Number: " ++ show n)
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
請注意,稱爲forM_
的組合器在Control.Monad
中定義,與我稱爲for
的組合器完全相同。
咦?那個編輯是關於什麼的? 'forM_'是正確的名稱,[由標準庫使用](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Foldable.html#v:forM-95 - )。 – leftaroundabout 2015-01-03 12:06:26
由於我提供的定義,我覺得我可以稱之爲任何我想要的。把它稱爲「for」使命令式語言的類比更清晰。還有[先例](https://www.haskell.org/hoogle/?hoogle=for)。我認爲堆棧溢出(主要是教學法)的答案不應該被標準庫中的約定所約束(這需要權衡教學法和便利性以適應其他類似命名的操作系統的需要,功能)。 – 2015-01-03 13:57:50
你的意思是系列'[0,1,0,2,0,3]'? – poitroae 2013-02-10 13:03:16
只是你知道,你使用的術語不正確。 'IO'是一個monad,'IO()'(和'IOInt','IO a'等等)是一個類型,而'foo 0'是一個IO()類型的值像'foo 0'是「行動」,「一元行動」或「一元計算」)。所以你試圖連接(或者更常見的「順序」)動作,而不是單子 - 這裏只有一個monad,它是'IO'。 – luqui 2013-02-11 11:52:34