我已经开始尝试Haskell并遇到问题 . qqq是一个函数,如果使用“Nothing”调用则应打印一个字符串,如果使用“Just something”调用则打印其他内容 .
第一次尝试似乎工作:
qqq Nothing = print "There isn't anything to be printed."
qqq (Just x) = print "There is something to be printed." >> print x
main :: IO ()
main = qqq (Just 43)
但:
-
当我试图使
main = qqq (Nothing)
失败时("Ambiguous type variable `a0' in the constraint: (Show a0) arising from a use of 'qqq'") -
当我想添加类型签名时如果失败:
-
qqq :: Maybe x => x -> IO ()
- >Type constructor 'Maybe' used as a class
- >不是吗? -
qqq :: (Maybe x) -> IO ()
. 现在签名本身看起来很成功 . 但main = qqq (Just 43)
开始失败,如main = qqq (Nothing)
案例那样神秘的(Show a0)
错误 .
问题:
-
为什么用
Nothing
调用qqq与使用Just 43
调用有什么不同? -
(Show a0)
是什么?它仅在错误消息中提及 . 任何使用它的尝试都会导致像"Show not in the scope"这样的东西 . -
这是什么类型的正确签名?如何推导Haskell打印类型签名?期待像:
f 0 = 2
f x = (f (x-1)) + 3
main = print get_type_as_string(f)
-- prints "Number -> Number"
1 回答
qqq
的类型是:这意味着
qqq
采用Maybe a
类型的一个参数并返回没有值的IO操作,其约束为a
实现Show
类型类 . 要找出Show
是什么,您可以在ghci中使用:i Show
.Show
是一个类型类,它要求可以将类型的值转换为字符串 .qqq
具有约束,因为print
想要打印出值(print
的类型为Show a => a -> IO ()
) .Maybe
不是类型类,而是数据类型 . 您可以阅读有关类型here的更多信息 .您可以让GHC通过在.hs文件中键入函数,然后使用ghci(
ghci Myfile.hs
)加载文件,然后键入:t qqq
来显示类型来推断类型签名 . 您还可以使用let qqq n = case n of { Nothing -> print "abc"; Just x -> print "def" >> print x }
在交互式会话中定义函数(它看起来有点不同,因为函数定义必须在ghci中的一行上,但含义相同) .当main调用
qqq
和qqq (Just 43)
时,很明显Maybe a
的具体类型是数字类型(ghci默认为Integer),因此qqq
具有Maybe Integer -> IO ()
的具体类型 . 但是,使用qqq Nothing
,a
的主要调用qqq
可以是任何内容(它是不明确的)并且ghci报告错误 .