【发布时间】:2020-01-08 13:17:28
【问题描述】:
虽然我觉得对 Haskel IO 和 Monads 有很好的了解,但我很难理解以下错误消息。
考虑一下 Haskell 中的以下简单函数
testf :: Show a => a -> String
testf x = show x
我尝试使用 IO Monad 实现一个打印到控制台的变体
printtoscreen :: Show a => a -> IO()
printtoscreen x = putStrLn . show x
但是,这会产生以下错误:
无法将类型“[Char]”与“a0 -> String”匹配 预期类型:a0 -> 字符串 实际类型:字符串
正确的版本应该省略显式声明x 参数
printtoscreen :: Show a => a -> IO()
printtoscreen = putStrLn . show
我理解为什么最后一个代码 sn-p 有效,但我无法理解第二个代码 sn-p 的错误消息,因为它也会返回一个字符串到 putStrLn
那么,IO() 变体中为什么要省略 x 参数?
【问题讨论】:
-
putStrLn . show x表示\y -> putStrLn (show x y),所以你用printtoscreen x y = putStrLn (show x y)实现了一个函数。因此这意味着show应该具有Show a => a -> b -> String类型,但类型当然是Show a => a -> String。 -
说得通,
putStrLn (show x)确实有效!非常感谢,原来这个错误超出了 IO Monads 的范围 -
这里的问题是
putStrLn . show x被解析为putStrLn . (show x)而不是(putStrLn . show) x。这是因为函数应用程序show x的优先级高于任何二元运算符:这就是1 + f x在没有额外括号的情况下正确的原因。 -
可能不是严格意义上的重复,但阅读答案here 应该可以帮助您更好地了解正在发生的事情。