【问题标题】:Using Haskell's "Maybe", type declarations [beginner's question]使用 Haskell 的“Maybe”,类型声明 [初学者的问题]
【发布时间】:2011-07-16 08:43:14
【问题描述】:

我已经开始尝试使用 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) 案例中一样。

问题:

  1. 为什么用Nothing调用qqq和用Just 43调用有很大不同?
  2. 什么是(Show a0)?它仅在错误消息中提及。任何使用它的尝试都会导致类似“显示不在范围内”的结果。
  3. 什么是正确的类型签名?如何制作它推导出的 Haskell 打印类型签名?期待类似的东西:
f 0 = 2
f x = (f (x-1)) + 3

main = print get_type_as_string(f)
-- prints "Number -> Number"

【问题讨论】:

    标签: haskell nothing maybe type-signature


    【解决方案1】:

    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 }定义函数(看起来有点不同,因为函数定义在ghci中必须在一行,但意思是一样的)。

    main 调用qqqqqq (Just 43) 时,很明显Maybe a 的具体类型是数字类型(ghci 默认为Integer),所以qqq 的具体类型为Maybe Integer -> IO ()。但是,qqqqqq Nothinga 的主要调用可能是任何东西(它是模棱两可的),ghci 会报告错误。

    【讨论】:

    • 还回答了未提出的问题“为什么我不能在 ghci 中设置任何东西,它会抱怨 parse error on '='
    • “模糊类型”在 Haskell 中是否总是失败,或者它可以决定“类型在这里很重要,所以有时让它变得模糊”?
    • 当编译器不知道该做什么时,Haskell 抱怨类型不明确。因此,如果编译器可以找出类型将是什么就没有问题,但如果必须在没有足够信息的情况下推断类型,则会出现错误。
    • GHC 扩展 ExtendedTypeDefaulting 有时会允许 ghc 选择默认类型而不是报告模棱两可的类型错误。
    • 请注意,您不必将 qqq 重写为case 以使其在 ghci 中工作。您只需在开头添加一个let 并用; 替换换行符,如下所示:let qqq Nothing = print "..."; qqq (Just x) = print "..." >> print x
    猜你喜欢
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 2013-05-02
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多