我已经开始尝试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)
时失败(“约束中的歧义类型变量'a0':(显示a0),是由于使用'qqq'而引起的”))qqq :: Maybe x => x -> IO ()
-> Type constructor 'Maybe' used as a class
->但这不是吗? qqq :: (Maybe x) -> IO ()
。现在签名本身看起来像成功。但是main = qqq (Just 43)
开始失败,并出现像(Show a0)
一样的神秘main = qqq (Nothing)
错误。 问题:
Nothing
调用qqq与用Just 43
调用有很大不同? (Show a0)
?仅在错误消息中提到它。任何使用它的尝试都会导致类似“不在范围内显示”之类的信息。 f 0 = 2
f x = (f (x-1)) + 3
main = print get_type_as_string(f)
-- prints "Number -> Number"
最佳答案
qqq
的类型是:
qqq :: Show a => Maybe a -> IO ()
这意味着
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 }
在交互式 session 中定义函数(它看起来有点不同,因为函数定义必须在ghci中位于一行,但是含义相同)。当main用
qqq
调用qqq (Just 43)
时,很明显Maybe a
的具体类型是数字类型(ghci默认为Integer),因此qqq
具有Maybe Integer -> IO ()
的具体类型。但是,主调用qqq
和qqq Nothing
,a
可能是任何东西(模棱两可),并且ghci报告错误。