haskell - 不同数据构造函数的函数

标签 haskell

一周前我开始学习 Haskell,遇到了一个奇怪的问题。我创建了一个简单的数据类型并希望在控制台中显示它。我为我的类型的 2 个构造函数创建了 2 个函数。如果我使用带有 2 个参数的构造函数,编译器可以调用函数。但它不能调用另一个应该捕获带有 1 个参数的构造函数的函数。

module Main (
    main
) where

data MyContainter a b = FirstVersion a b
                  | SecondVersion a
                  deriving(Show,Eq)

showContainer (FirstVersion a b) = show b
showContainer (SecondVersion a) = show a

--startF = showContainer (FirstVersion 1 2) -- it works
startF = showContainer (SecondVersion 1) -- it doesn't work

main = putStr startF

编译器告诉:
Ambiguous type variable `a0' in the constraint:
  (Show a0) arising from a use of `showMaybe'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: showMaybe (SecondVersion 1)
In an equation for `startF': startF = showMaybe (SecondVersion 1)

为什么这么说?我直接创建了(SecondVersion 1),不明白为什么编译器不调用showContainer(SecondVersion a)。

最佳答案

问题是 showContainer具有以下类型:

showContainer :: (Show a, Show b) => MyContainer a b -> String

但是当你通过 SecondVersion 1 ,不知道是什么b是,因为 SecondVersion 1适用于任何类型的 b !当您通过 FirstVersion ,它工作正常,因为,如 FirstVersion包含两个 ab ,对于它们应该是什么,从来没有任何歧义。

因此,由于编译器无法知道 b你想要的,而且无从得知b的选择不影响 showContainer (毕竟,它确实会影响您传递 FirstVersion 时的行为,因为它使用 show 类型的值 b ),它放弃了。

这就是错误消息的含义:类型变量 a0 1 是模棱两可的,所以请添加一个类型签名来告诉我它是什么。在这种情况下,它是什么并不重要,因此您可以将其设置为 () :
startF = showContainer (SecondVersion 1 :: MyContainer Integer ())

您可能不会经常遇到这样的错误,因为您使用这些值的上下文通常会强制使用特定的 b要使用的。

1 不幸的是,GHC 在选择类型变量方面并不是最好的;如果你给 showContainer像我展示的那样显式类型签名,然后它会使用 b在错误消息中。

关于haskell - 不同数据构造函数的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9142863/

相关文章:

windows - cabal 安装 glib 出错

haskell - yesod-sqlite 模板中的 "import Database.Persist as X hiding (get)"是如何工作的

haskell - 在 cabal 构建中包含数据文件

haskell - 为什么 "cabal sdist"不包含所有 "files needed to build"?

haskell - 如何正确更新 Data.IORef 中保存的 Haskell 记录?

haskell - 安装可执行文件时硬编码 datadir 路径

haskell - 累加器参数如何发送给函数?

haskell - 复合镜头不能让绑定(bind)吗?

haskell - 我是否需要采取明确的操作来促进与持久数据结构的共享?

haskell - 如何在 Haskell 中使用 hedis 通过 Unix 域套接字连接到 redis 服务器?