如何在Haskell中使用map打印List?

问题描述 投票:0回答:2

抱歉,如果我很傻,但我是 Haskell 的初学者,我正在尝试用 putStrLn 打印列表,但我不知道如何解决下一个问题:

我正在尝试使用以下代码在 Haskell 中制作一个基本的打印列表:

import System.IO

array = map show [1, 2, 3, 4]

main :: IO ()
main = do
  map putStrLn array

但是编译器给了我:

 8 main.hs:7:3: error:                                                                                                          
  7     • Couldn't match expected type ‘IO ()’ with actual type ‘[IO ()]’                                                            
  6     • In a stmt of a 'do' block: map putStrLn array                                                                              
  5       In the expression: do map putStrLn array                                                                                   
  4       In an equation for ‘main’: main = do map putStrLn array 

我该如何解决?

haskell
2个回答
4
投票

Haskell 处理 IO 的方式与其他语言截然不同。

在像 Java 这样的语言中,

System.Out.println(3)
是一个不会求值的语句,所以你甚至不能写像
x = System.Out.println(3);
这样的东西。

在像 Lisp 这样的语言中,

(print 3)
计算结果为 3,并且在计算过程中打印
3
。因此,说出类似
(setq x (print 3))
的内容会将
x
的值设置为
3
并打印
3

在 Haskell 中,

putStrLn "3"
表示打印
3
的命令。因此,说
x = putStrLn "3"
除了将
x
分配给命令
putStrLn "3"
之外,绝对没有任何作用。

让我们看看一些类型。我们有

map :: (a -> b) -> [a] -> [b]
putStrLn :: String -> IO ()

因此,我们应该有

map putStrLn :: [String] -> [IO ()]
map putStrLn array :: [IO ()]

换句话说,

map putStrLn array
是一个“IO操作”列表,它会产生
()
类型的值(基本上,这意味着执行操作不会产生额外的信息)。

但是,为了写

main :: IO ()
main = map putStrLn array

这是什么

main :: IO ()
main = do map putStrLn array

翻译为,我们需要

map putStrLn
IO ()
类型,而不是
[IO ()]
类型。

如果您希望对列表中的每个元素执行操作,可以使用

for_
函数,其类型为
for_ :: (Foldable g, Applicative f) => g a -> (a -> f ()) -> f ()
IO
Applicative
并且
[]
Foldable
,所以特别是
for_ :: [String] -> (String -> IO ()) -> IO ()
for_
可以采用的一种类型。代码看起来像

import Data.Foldable (for_)

array :: [String]
array = map show [1, 2, 3, 4]

main :: IO ()
main = for_ array putStrLn

这在命令式语言中相当于

for each x in array do {
    putStrLn x;
}

0
投票

main
需要
IO
单子,因此您需要在
IO
单子内部进行映射,而不是错误所述的
List of IO
mapM_
可以完成这项工作。
mapM_
吃单子函数和某些东西的列表,它映射到单子内部。打印字符串时,结果将是
IO ()

array = map show [1, 2, 3, 4]

main :: IO ()
main = do
  mapM_ putStrLn array

这是结果:

1
2
3
4
© www.soinside.com 2019 - 2024. All rights reserved.