我正在阅读他们的wiki上Haskell中IO monad的更深层次的工作, 我遇到了这段代码
main = do a <- ask "What is your name?"
b <- ask "How old are you?"
return ()
ask s = do putStr s
readLn
Run Code Online (Sandbox Code Playgroud)
这对我来说很有意义.ask函数应该打印出给它的字符串并返回一行可以传递给a或b.
然而,加载到GHCi我遇到问题.告诉我没有使用read的读取实例,我可以导入GHC.Read.这不应该是必要的.这段代码在Haskell.org上,所以我认为它应该有效.语言中的某些东西是否发生了变化,或者是否存在一些我缺失的重要理解?
如果你创建一个只有ask函数的文件(没有有问题的main)并将其加载到ghci,你将能够看到ask的类型是
ask :: (Read a) => String -> IO a
Run Code Online (Sandbox Code Playgroud)
意味着它在返回类型中是多态的.
问题是,当你这样做
a <- ask "What is your name"
Run Code Online (Sandbox Code Playgroud)
编译器需要知道什么是类型,a因此它可以使用正确的反序列化函数为您从输入读取的行.但是a在其他任何地方都没有使用,也没有任何类型的签名,所以类型推断不能推断出类型a.编译器放弃并为您提供"ambiguos类型"消息.
有两种主要方法可以解决这个问题:
使ask函数始终返回相同的类型.您可以通过添加特定签名来执行此操作
ask :: String -> IO String
Run Code Online (Sandbox Code Playgroud)
或者通过改变readLn成类似的东西getLine.
在使用多态函数的位置添加类型签名.您可以在问题调用本身中添加类型签名:
a <- ask "What is your name" :: IO String
Run Code Online (Sandbox Code Playgroud)
或者您可以将其直接添加到变量中
(a :: String) <- ask "What is your name"
Run Code Online (Sandbox Code Playgroud)
但是,默认的Haskell语法不允许使用第二个选项.您需要通过添加以下注释作为文件的第一行来启用ScopedTypeVariables扩展
{-# LANGUAGE ScopedTypeVariables #-}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
269 次 |
| 最近记录: |