允许未标记的联合等同于允许类型类?

Thr*_*eFx 1 haskell type-theory subtyping

这个问题中,未标记的联合被描述为一种子类型.

类型类也是子类型的一种形式.

它们在概念上是等同的吗?他们是,我将如何在Haskell中实现这些?

dup*_*ode 5

类型类也是子类型的一种形式.

他们不是.为了便于说明,让我们回到我在该问题中提到的TypeScript示例:

如果我们有一个具有union类型的值,我们只能访问union中所有类型共有的成员.

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function getSmallPet(): Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim();    // errors
Run Code Online (Sandbox Code Playgroud)

这里,返回类型getSmallPet既不是Fish也不是Bird,但都具有作为成员的其他成员共同两者的超类型FishBird.一个Fish一个Fish | Bird,所以是一个Bird.

类型类会发生什么不同:

foo :: Num a => a -> a
foo x = (x * x) + x
Run Code Online (Sandbox Code Playgroud)

虽然这两个foo (3 :: Integer)foo (7.7 :: Double)工作,这并不意味着有对应于超Num(3 :: Integer),并(7.7 :: Double)也有.相反,所有Num a => a -> a说的是,你的选择a应具有的一个实例Num(这是值得强调的是,Num不是一个类型),以便有合适的实现(*)(+)您所选择的类型.不同于OOP方法,(*)并且(+)不属于任何特定类型的,所以它是没有必要的,以便既使用它们引入超IntegerDouble.

  • @ThreeFx我们可以说,在这种情况下,它们将是实现相同目标的两种截然不同的方式.顺便说一下,值得注意的是,未标记的方面对于讨论来说并不重要 - 如果我们在TypeScript示例中有一个带有`layEggs`方法的`Oviparous`接口,`Fish`和`Bird`会扩展,根本差异将保持不变.一个相关的,如果有些切向的问题:[*Parametric polymorphism vs Ad-hoc polymorphism*](http://stackoverflow.com/q/6730126/2751851). (3认同)