开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜