Haskell将[IO String]加入IO String的方法

时间:2010-12-09 19:20:46

标签: haskell io monads

我的目标是编写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

5 个答案:

答案 0 :(得分:19)

答案 1 :(得分:6)

除了ephemient指出的,我认为你有一个语法问题:你使用++运算符的方式使你看起来像是试图用操作数{{调用++运算符1}}和foldl。将[]运算符放在括号中以明确您的意图:

++

答案 2 :(得分:5)

您要查找的功能是sequence,但应注意

sequence (replicate n f)

相同
replicateM n f

foldl (++) []相当于concat。所以你的功能是:

readNLines n = liftM concat (replicateM n getLine)

或者,如果您想保留换行符:

readNLines n = liftM unlines (replicateM n getLine)

答案 3 :(得分:1)

我能想出的最短答案是:

import Control.Applicative
import Control.Monad

readNLines :: Int -> IO String
readNLines n = concat <$> replicateM n getLine

答案 4 :(得分:0)

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值列表,而不是简单地返回一个动作列表