将putStr应用于列表的每个项目

Don*_*nna 8 printing haskell list

我正在尝试以这种格式打印出一个整数列表

[1]
[2]
[3]
Run Code Online (Sandbox Code Playgroud)

所以我的函数获取一个整数列表并返回一个IO(),如下所示:

import System.IO

printVector :: [Integer] -> IO ()
printVector (x:xs) = putStr("[" ++ show(x) ++ "]" ++ "\n") : printVector xs
Run Code Online (Sandbox Code Playgroud)

但是ghc给了我错误:

lin-test.hs:5:22:
Couldn't match expected type `IO ()' with actual type `[a0]'
In the expression:
  putStr ("[" ++ show (x) ++ "]" ++ "") : printVector xs
In an equation for `printVector':
    printVector (x : xs)
      = putStr ("[" ++ show (x) ++ "]" ++ "") : printVector xs
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

现在我的理解是函数将遍历列表,首先是第一个项'x',然后是:printVector xs它会递归调用列表的其余部分,将相同的putStr函数应用于列表中的每个项目.

但我认为我的问题出在我的位置:printVector xs?谁能指出我在这里做错了什么?

tho*_*ron 14

您需要映射列表,但由于这些是IO操作,您还需要执行它们(因为map它将返回IO操作列表而不执行它们,请参阅下面的示例).

sequence $ map (putStrLn . show) [1,2,3,4]
Run Code Online (Sandbox Code Playgroud)

有一个功能已经做到了,它是mapM.所以这个例子可以简化为:

mapM (putStrLn . show) [1,2,3,4]
Run Code Online (Sandbox Code Playgroud)

您可以做的另一件事是使用相反的使用mapM_,sequence_并忽略对每个元素执行IO操作的结果.因此,返回类型将IO ()代替IO [()](前一个示例).

mapM_ (putStrLn . show) [1,2,3,4]
Run Code Online (Sandbox Code Playgroud)

  • @enkitosh:拆分IO和格式:`mapM_(putStr.格式)[1..4]`和`format x ="["++ show x ++"] \n"`. (4认同)
  • @enkitosh使用lambda,`mapM_(\ N - > putStrLn $ "[" ++表演n ++ "]")[1,2,3,4]`,或,IMO的可读性,`进口Control.Monad (forM_)`和`forM_ [1,2,3,4] $ \n - > putStrLn $"["++ show n ++"]"`.(`forM_ = flip mapM_`) (4认同)