【问题标题】:putStrLn IO() error when trying to display a list尝试显示列表时出现 putStrLn IO() 错误
【发布时间】:2019-03-05 23:04:30
【问题描述】:

我正在玩弄自定义列表显示。这个概念非常简单,但我不断收到 IO() 错误。我的代码是:

displayList :: [Int] -> IO()
displayList [] = putStrLn ""
displayList (firstUnit:theRest) =  putStrLn (show firstUnit ++ "\n" ++ 
                                   displayList theRest)

我得到的错误代码是:

• Couldn't match expected type ‘[Char]’ with actual type ‘IO ()’
• In the second argument of ‘(++)’, namely ‘(displayList theRest)’
  In the first argument of ‘putStrLn’, namely
    ‘((show firstUnit) ++ (displayList theRest))’
  In the expression:
    putStrLn ((show firstUnit) ++ (displayList theRest))

出现错误的行的特定部分是 displayList theRest 而不是 putStrLn ((show firstUnit) ++ 部分。

我想我理解正在发生的事情,即当displayList theRest 在错误行中被调用时,它最终有可能在几次递归调用后从displayList [] = putStrLn "" 行返回一个 IO() 类型,即不支持作为 putStrLn 函数中的输入。有人知道解决这个问题的方法吗?

【问题讨论】:

  • displayList 在任何情况下都不会返回字符串。它总是返回IO,所以... ++ displayList theRest 没有意义。你最好有这个函数构造并返回一个字符串,然后根据需要打印字符串。
  • 问题是你试图将String(或[Char],意思相同)与displayList的结果连接起来,即IO () - 它是很明显你不能这样做。我不确定您希望如何输出,但您可能想调用putStrLn (show firstUnit),然后在theRest 上递归调用displayList。 “then”是指对 2 个 IO 操作进行排序,可以在 do 块中或使用 >> 运算符(相同,这是 do 块转换为的内容)。
  • 在任何编程语言(包括命令式语言)中都会遇到同样的问题。您需要弄清楚您是否希望displayList 构建并返回一个字符串,或者它是否应该输出内容(并且什么都不返回)。
  • 你目前的情况就像是在说printf("%d\n%s", firstUnit, printf(theRest))...

标签: haskell io


【解决方案1】:

问题

您的代码的问题相当明显:正如编译器告诉您的那样,您试图将字符串 (((show firstUnit) ++) 与 IO()(函数的返回类型)连接起来

解决方案

解决方案可以采用两条路径:要么您需要一个返回整个字符串的函数,然后将其全部打印出来,要么只是递归地逐步打印。我的意思是:

返回一个字符串

displayList :: [Int] -> IO()
displayList = putStrLn . helper
  where
    helper :: [Int] -> String
    helper [] = ""
    helper (n:ns) = show n ++ "\n" ++ helper ns

这种方法效果很好,但我认为它不整齐也不清晰。

更好的版本

displayList' :: [Int] -> IO()
displayList' [] = putStrLn ""
displayList' (n:ns) =  putStrLn (show n) >> displayList' ns

我想你可以看到这个版本更容易阅读。另请注意,print :: Show a => a -> IO() 的工作方式与putStrLn . show 完全相同

【讨论】:

  • 更好的版本:displayList ns = mapM_ print ns
猜你喜欢
  • 2021-03-22
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2012-11-20
  • 1970-01-01
  • 2021-06-16
相关资源
最近更新 更多