【问题标题】:Couldn't match expected type when defining data type定义数据类型时无法匹配预期类型
【发布时间】:2018-07-16 18:43:49
【问题描述】:

我正在尝试定义我自己的包含 Odds 的数据类型:

data Odd = Odd Integer deriving (Eq, Show)

instance Enum Odd where
  succ x = Odd $ x + 2
  pred x = Odd $ x - 2

当我尝试编译它时,我得到:

hello.hs:92:18: error:
    • Couldn't match expected type ‘Integer’ with actual type ‘Odd’
    • In the second argument of ‘($)’, namely ‘x + 2’
      In the expression: Odd $ x + 2
      In an equation for ‘succ’: succ x = Odd $ x + 2
   |
92 |   succ x = Odd $ x + 2
   |                  ^^^^^
Failed, no modu

我不明白为什么 haskell 期望 Integer 在左侧,我们不是将 Enum 实例定义为 Odd,而不是 Integer 吗?

【问题讨论】:

  • succ 的类型为Enum a => a -> a,因此您定义中x 的类型为Oddx + 2 因此是一个类型错误。看起来你想做succ (Odd x) = Odd $ x + 2之类的事情?
  • @Lee (Odd x) 确实有效,但为什么呢?正如你所说,x + 2 给我一个类型错误。
  • succ 实现的参数类型为 Oddsucc (Odd x) 匹配 Odd 类型(也称为 Odd)的唯一构造函数。现在x 的类型为Integer,所以x + 2 是有效的。

标签: haskell


【解决方案1】:

从语法上讲,您在这里的目标是Integer 添加到Odd 对象。由于 Haskell 中的加法要求两个操作数的类型相同,而且 Odd 无论如何都不是 Num 类型,因此编译器会抱怨这是不可能的。

但是,您可以获取包装在 Odd 构造函数中的元素,然后处理该元素。例如:

instance Enum Odd where
  succ (Odd x) = Odd (x+2)
  pred (Odd x) = Odd (x-2)

因此,我们在这里通过与Odd x 进行模式匹配来获得包装在Odd 构造函数中的Integer x,然后我们可以进一步处理该整数x。例如,向其添加两个,并将其包装在另一个 Odd 构造函数中。

【讨论】:

  • 谢谢,现在清楚多了。我怎么能像succ x = x + (Odd 2) 那样工作?有可能吗?
  • @aryndin:通过使Odd 成为Num 的实例(就像您在此处为Enum 所做的那样。请参见此处:hackage.haskell.org/package/base-4.11.1.0/docs/…
  • @aryndin ...但您可能不想让Odd 成为Num 的实例。我从名称和 Enum 实例猜测您打算 Odd 只包含奇数;但是Num 需要fromInteger :: Integer -> Odd,这样你也可以注入偶数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 2015-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多