【问题标题】:Haskell way to join [IO String] into IO StringHaskell 方法将 [IO String] 加入 IO String
【发布时间】:2011-05-23 01:50:54
【问题描述】:

我的目标是编写 Haskell 函数,它从输入中读取 N 行并将它们连接到一个字符串中。下面是第一次尝试:

readNLines :: Int -> IO String
readNLines n = do
  let rows = replicate n getLine
  let rowsAsString = foldl ++ [] rows 
  return rowsAsString  

这里有关于foldl的haskell投诉:

无法匹配预期类型[a]' against inferred type(a1 -> b -> a1) -> a1 -> [b] -> a1'

据我了解,行的类型是[IO String],是否有可能将此类列表加入单个IO String

【问题讨论】:

    标签: haskell io monads


    【解决方案1】:
    【解决方案2】:

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

    foldl (++) [] rows
    

    【讨论】:

    • 啊,是的,这是类型检查错误的直接原因……我忽略了,因为即使在 OP 修复之后,他们仍然有另一个问题。
    • 还应注意foldl (++) []concat相同。
    【解决方案3】:

    你要找的函数是sequence,不过需要注意的是

    sequence (replicate n f)
    

    相同
    replicateM n f
    

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

    readNLines n = liftM concat (replicateM n getLine)
    

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

    readNLines n = liftM unlines (replicateM n getLine)
    

    【讨论】:

    • concatfoldr (++) [],而不是 foldl:适用于无限的列表流。在后面的示例中,您也缺少 n 作为 replicateM 的参数。但是,是的,这些都是好点。
    • @ephemient,感谢提醒,我用 n 修复了错误,是的,concat 真的是foldr (++) [],我的意思是他写了foldl (++) [],这相当于@ 987654336@,虽然正如你提到的,concat 实际上更好,因为它适用于无限流。
    【解决方案4】:

    我能想到的最短答案是:

    import Control.Applicative
    import Control.Monad
    
    readNLines :: Int -> IO String
    readNLines n = concat <$> replicateM n getLine
    

    【讨论】:

      【解决方案5】:

      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
      

      这两个都使用单子复制 (replicateM),它按顺序评估单子值列表,而不是简单地返回操作列表

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-11
        • 2013-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-02
        • 2011-12-30
        相关资源
        最近更新 更多