[英]Haskell way to join [IO String] into IO String
我的目標是編寫Haskell函數,它從輸入中讀取N行並將它們連接成一個字符串。 以下是第一次嘗試:
readNLines :: Int -> IO String
readNLines n = do
let rows = replicate n getLine
let rowsAsString = foldl ++ [] rows
return rowsAsString
這里有關於foldl
抱怨:
無法匹配預期類型
[a]' against inferred type
(a1 - > b - > a1) - > a1 - > [b] - > a1'
據我所知,行的類型是[IO String]
,是否有可能在單個IO String
加入這樣的列表?
除了ephemient指出的,我認為你有一個語法問題:你使用++
運算符的方式使它看起來像你試圖用操作數foldl
和[]
調用++
運算符。 將++
運算符放在括號中以使您的意圖清晰:
foldl (++) [] rows
您正在尋找的功能是sequence
,但應注意
sequence (replicate n f)
是相同的
replicateM n f
而foldl (++) []
相當於concat
。 所以你的功能是:
readNLines n = liftM concat (replicateM n getLine)
或者,如果您想保留換行符:
readNLines n = liftM unlines (replicateM n getLine)
我能想出的最短的答案是:
import Control.Applicative
import Control.Monad
readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine
replicate
返回IO String
操作列表。 為了執行這些操作,需要在IO monad中運行它們。 所以你不想加入一系列IO動作,而是按順序運行它們並返回結果。
這就是我要做的
readNLines :: Int -> IO String
readNLines n = do
lines <- replicateM n getLine
return $ concat lines
或者,在應用風格:
import Control.Applicative
readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine
這兩個都使用monadic replicate(replicateM),它按順序計算monadic值列表,而不是簡單地返回一個action列表
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.