Haskell way to join [IO String] into IO String
my goal is to write Haskell function which reads N lines from input and joins them in one string. Below is the first attempt:
readNLines :: Int -> IO String
readNLines n 开发者_运维知识库= do
let rows = replicate n getLine
let rowsAsString = foldl ++ [] rows
return rowsAsString
Here haskell complaints on foldl
:
Couldn't match expected type
[a]' against inferred type
(a1 -> b -> a1) -> a1 -> [b] -> a1'
As I understand type of rows is [IO String]
, is it possible some how join such list in a single IO String
?
You're looking for sequence :: (Monad m) => [m a] -> m [a]
.
(Plus liftM :: Monad m => (a1 -> r) -> m a1 -> m r
and unlines :: [String] -> String
, probably.)
Besides what ephemient points out, I think you have a syntax issue: The way you're using the ++
operator makes it look like you are trying to invoke the ++
operator with operands foldl
and []
. Put the ++
operator in parentheses to make your intent clear:
foldl (++) [] rows
The functions you are looking for is is sequence
, however it should be noted that
sequence (replicate n f)
is the same as
replicateM n f
And foldl (++) []
is equivalent to concat
. So your function is:
readNLines n = liftM concat (replicateM n getLine)
Alternatively if you want to preserve line breaks:
readNLines n = liftM unlines (replicateM n getLine)
The shortest answer I can come up with is:
import Control.Applicative
import Control.Monad
readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine
replicate
returns a list of IO String
actions. In order to perform these actions, they need to be run in the IO monad. So you don't want to join an array of IO actions, but rather run them all in sequence and return the result.
Here's what I would do
readNLines :: Int -> IO String
readNLines n = do
lines <- replicateM n getLine
return $ concat lines
Or, in applicative style:
import Control.Applicative
readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine
Both of these use the monadic replicate (replicateM), which evaluates a list of monadic values in sequence, rather than simply returning a list of actions
精彩评论