[英]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.