【问题标题】:Haskell- IO String get multiple LinesHaskell- IO String 获取多行
【发布时间】:2013-03-25 18:02:50
【问题描述】:

我正在尝试编写一个函数,它可以获取多个字符串输入并在一个空行 ('\n') 上终止,我已经关注了

getLines :: IO [String]
getLines = do x <- getLine
           if x == ""
           return ()
           else do xs <- getLines
                return (x:xs)

编译失败,说 if 语句有问题

理想情况下我想这样工作

获取线

苹果

(按下回车键)

输出: [“苹果”、“鸟”、“猫”]

【问题讨论】:

    标签: string list haskell io


    【解决方案1】:

    if 之后需要then,并且()(空元组)应该是[](空列表)。在if 中,如果thenelse 在不同的行上,它们也需要缩进,因为if then else 是一个运算符,编译器需要知道表达式继续。您的缩进需要调整,以使所有内容的缩进都超过前导do

    getLines :: IO [String]
    getLines = do x <- getLine
                  if x == ""
                    then return []
                    else do xs <- getLines
                            return (x:xs)
    

    或者所有内容都比包含前导do缩进更多:

    getLines :: IO [String]
    getLines = do
      x <- getLine
      if x == ""
        then return []
        else do
          xs <- getLines
          return (x:xs)
    

    作为风格问题,您也可以使用null x 代替x == ""

    【讨论】:

    • (x:) &lt;$&gt; getLines 也是可能的。从定义上看并不是更好,但在这种情况下,我更喜欢do-notation。不过需要import Control.Applicative ((&lt;$&gt;))
    • @Zoidberg:是的,我通常更喜欢应用风格,但不想过度更改示例。它也可以写成getLines = untilNull getLine,其中untilNull 被定义为无点和无空间为execWriterT.fix.ap(liftM(=&lt;&lt;)(ap(unless.null).ap(liftM(&gt;&gt;)(tell.(:[]))).const)).const.lift,并带有适当的导入。
    【解决方案2】:

    这几乎是对的。

    if 之后需要一个then。您可能还需要稍微更改缩进,以便所有内容都缩进到x 而不是do。我认为应该这样做。

    【讨论】:

    • 目前也不会进行类型检查,我认为return ()应该是return [][] 为空列表,() 为单位。
    猜你喜欢
    • 2011-05-23
    • 2019-02-07
    • 2015-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多