我已经开始尝试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)?仅在错误消息中提到它。任何使用它的尝试都会导致类似“不在范围内显示”之类的信息。
  • 什么是正确的类型签名?如何使Haskell得出打印类型签名?期望像:

  • 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 ()的具体类型。但是,主调用qqqqqq Nothinga可能是任何东西(模棱两可),并且ghci报告错误。

    10-08 12:37