涉及代数数据类型的类型类默认方法?

时间:2016-05-15 03:27:01

标签: haskell

我来自标准ML,并且是Haskell的新手,所以我仍然试图围绕精心设计的类型系统。我想创建一个模块,公开一个代数数据类型Expression a以及一些可以与Expression a类型的值一起使用的函数。仅此一点并不算太糟糕。小警告:我想将a类型限制在Num类型类中,以便函数可以将a值用作数字。还是不太糟糕;经过一番探讨之后,我相信我想用它来称之为“GADT”。

更大的警告:所以在大多数情况下,可以为Num类型类中的所有类型定义相同的函数。但是,如果aIntegral类型类中,我希望一些函数中的一些函数具有一些替代行为,如果a中有Fractional,则需要一些替代行为1}}类型类。但是在大多数情况下,所有Num类型的所有内容都是相同的,所以我不想为一般情况IntegralFractional分别重写所有内容,因为导致大量重复的代码。

据我所知,这称为“Ad hoc多态”,这是Haskell通过类型类系统支持的。但是,由于两个原因,这似乎更复杂:1,这是一个ADT,其构造函数必须在默认函数中使用,也必须在Integral特定的和Fractional特定的替代函数中使用。 2,IntegralFractional是类型类(不是类型)所以我不确定这是否会让它更难为它们制定特定的行为。

同样,我是Haskell的新手,所以我可能认为这一切都错了。

编辑以澄清。所有困难归结为:我想为Nums做一个默认行为,然后如果Num碰巧是一个积分则是一个替代行为,如果Num恰好是一个分数,则会有另一个替代行为。

1 个答案:

答案 0 :(得分:4)

首先,您想要对aNum的限制做什么并不需要像GADT那样精心设计的任何内容。如果您的类型为Expression a,函数为exprFunc,则可以按如下方式声明:

exprFunc :: Num a => Expression a -> Expression a

这样,exprFunc将只有Num的参数。至于你的第二个问题,在Haskell中做多态函数的唯一(接受)方法是通过类型类。因此,对于IntegralFractional的示例,最好的方法是执行以下操作。

class Num a => C a where
    exprMethod :: Expression a -> Expression a

现在,您可以为exprMethodFractional定义Integral的两个单独定义。

instance Fractional a => C a where
    exprMethod expr = <some code>

instance Integral a => C a where
    exprMethod expr = <some other code>