【问题标题】:Using type constraints across typeclass instances跨类型类实例使用类型约束
【发布时间】:2018-06-15 07:26:18
【问题描述】:

我正在尝试定义一个类型类 Plotable,它提供了一个函数 plotable 来返回一个表示图表 (x,y) 中坐标的元组,它的类型 xy 没有必须具体(即Double),我认为它们可以是任何数字类型(它们被移交给Chart)。

我希望plotable 能够处理Num a => Complex aNum a => (a, a),所以我写道:

class Plotable a where
  plotable :: Num b => a -> (b, b)

instance Num a => Plotable (a, a) where
  plotable = id

instance Num a => Plotable (Complex a) where
  plotable c = (realPart c, imagPart c)

这对我来说很有意义,但是我收到了错误:

Couldn't match type ‘a’ with ‘b’
  ‘a’ is a rigid type variable bound by
    the instance declaration
    at /Users/dan.brooks/Code/haskell/coding-the-matrix/src/TheField/Plot.hs:12:10-33
  ‘b’ is a rigid type variable bound by
    the type signature for:
      plotable :: forall b. Num b => (a, a) -> (b, b)
    at /Users/dan.brooks/Code/haskell/coding-the-matrix/src/TheField/Plot.hs:13:3-10
  Expected type: (a, a) -> (b, b)
    Actual type: (b, b) -> (b, b)

但是如果a 被限制为Num,并且b 被限制为Num,那么在这种情况下传递相同的值应该可以工作吗?这仅仅是编译器的限制吗?还是我滥用了类型类和类型约束?

【问题讨论】:

  • 社区:也许我们应该有一个参考 q/a 来解决与误解普遍和存在量化相关的问题。最近,这些开始变得越来越普遍。
  • “但是如果 a 被限制为 Num,b 被限制为 Num,那么在这种情况下传递相同的值应该可以工作”——当然不是,否则同样的论点适用于 bad :: a -> b; bad x = x .类型变量在判断上只等于它们自己,这就是为什么编译器说它不能匹配两个不同的类型变量。在某种程度上,这确实是编译器的一个限制——它限制了你编写完全错误的代码。

标签: haskell typeclass type-constraints


【解决方案1】:
plotable :: Num b => a -> (b, b)

表示其中任何一个都必须类型检查

plotable :: a -> (Int, Int)
plotable :: a -> (Integer, Integer)
plotable :: a -> (Double, Double)
...

换句话说,该多态类型向用户承诺plotable 可以使用用户可以选择的任何数字类型b

id :: a -> a不让用户选择b,所以不够通用。

【讨论】:

    猜你喜欢
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 2012-09-06
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 2017-10-03
    相关资源
    最近更新 更多