【问题标题】:Printing elements of a list on new lines在新行上打印列表的元素
【发布时间】:2011-03-13 13:51:32
【问题描述】:

我正在尝试将列表中的元素打印到新行上,但无法正常工作;

printElements :: [String] -> IO()
printElements (x:xs) =  print x (some kind of newline, then loop?) printElements xs

所以这个:

["1","2","2","4"]

会给出:

1
2
3
4

【问题讨论】:

    标签: haskell


    【解决方案1】:

    在大多数情况下,您不需要在列表上编写循环,它已经完成了。要使用 monadic 函数循环列表,您可以使用 mapM(如果您不关心结果,则使用它的 mapM_ 变体。)

    如果你使用print,对于["1","2","3","4"],你会得到:

    Prelude> mapM_ print ["1","2","3","4"]
    "1"
    "2"
    "3"
    "4"
    Prelude> 
    

    print其实是:

    print :: Show a => a -> IO ()
    print x = putStrLn (show x)
    

    show 函数将字符串 "1" 转换为 "\"1\""putStrLn 打印该字符串并换行。

    如果将print 替换为putStrLn,则删除转换步骤并直接打印字符串:

    Prelude> mapM_ putStrLn ["1","2","3","4"]
    1
    2
    3
    4
    Prelude> 
    

    现在我想提供另一种解决方案。 Haskell 的做事方式就是以纯粹的方式做尽可能多的事情,并且只在需要时使用 IO。

    所以在这种情况下,我们可以使用\n 连接所有要打印的字符串,并一次打印所有字符串。

    要连接所有字符串,有一个方便的函数:unlines

    Prelude> unlines ["1","2","3","4"]
    "1\n2\n3\n4\n"
    Prelude> 
    

    现在您只需打印它;请注意unlines 在列表的最后一项之后添加了一个换行符,所以我们将使用putStr 而不是putStrLn

    Prelude> putStr ( unlines ["1","2","3","4"] )
    1
    2
    3
    4
    Prelude> 
    

    【讨论】:

    • 我认为,即使输出相同,unlines 也是一个“更正确”的解决方案。
    • 如果列表很大,unlines 使用两倍的内存还是 Haskell 在这种情况下可以偷懒?
    • 我也对mapM_ putStrLnputStr . unlines的效率差异感兴趣
    • 如果我有一个自定义元素列表怎么办?在我的例子中是一些元组。
    • 如果show 可以打印您的元素,您可以使用putStr ( unlines $ map show [(1,"A"),(2,"B"),(3,"C"),(4,"D")]),但您可以将 show 替换为任何采用您的自定义类型并返回字符串的函数。
    【解决方案2】:

    你的功能是:

    printElements :: [String] -> IO()
    printElements [] = return ()
    printElements (x:xs) = do putStrLn x
                              printElements xs
    

    如果您已经了解 monad,可以使用mapM_ 函数:

    printElements :: [String] -> IO()
    printElements = mapM_ putStrLn
    

    注意:也许你必须阅读lyah 的第 8 章。

    【讨论】:

    • printElements (x:xs) = putStrLn x >> printElements xs 是第一个函数的另一种写法。
    【解决方案3】:

    您可以使用mapM_ 为每个元素调用putStrLn,而不是显式递归。它与用于列表的常规map 一样工作,但与一元函数一起使用(因此是“M”)。当您只关心副作用(在本例中为打印)而不关心映射函数的结果时,使用下划线变体。

    printElements :: [String] -> IO ()
    printElements = mapM_ putStrLn

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-09
      • 2012-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多