【问题标题】:Type classes in Haskell data typesHaskell 数据类型中的类型类
【发布时间】:2009-07-05 05:24:52
【问题描述】:

在 Haskell 中,可以这样定义数据类型:

data Point1 = Point1 {
    x :: Integer
  , y :: Integer
}

可以对数据类型中的变量使用类型类吗?如果有怎么办?我意识到可以将其作为代数数据类型来执行,对每种类型的点都有不同的定义,但我想知道是否有办法以更紧凑和灵活的方式完成此操作。

例如类似于此 pseudocode 的内容,它使用函数声明语法:

data Point2 = Point2 {
    x :: (Num a, Ord a) => a
  , y :: (Num a, Ord a) => a
}

目标是允许将 IntIntegerFloatDouble 值存储在数据类型。理想情况下,我想限制它,使 x 和 y 必须是同一类型。

【问题讨论】:

    标签: haskell types typeclass


    【解决方案1】:

    您需要决定是否要对该类型进行存在量化或普遍量化。万能量化,阿拉:

    data (Num a, Ord a) => Point2 a = Point2 a a
    

    产生了 Num 和 Ord 实例存在于类型“a”的证明义务,但实际上并没有太大帮助,因为它所做的只是在您通过构造一个值来使用 Point 类时给您一个义务那种类型的或者当你去模式匹配它的时候。

    在几乎所有情况下,你最好定义

    data Point2 a = Point2 a a deriving (Eq,Ord,Show,Read)
    

    让您的每个实例都取决于您想要的额外信息。

    instance Num a => Num (Point2 a) where
        ...
    
    instance (Num a, Ord a) => SomeClass (Point2 a) where
        ...
    

    这让您可以绕过并构建更少的多余字典,并增加您的 Point2 数据类型可以使用的场景数量。

    另一方面,存在量化可以让你说你根本不在乎类型是什么(更接近你实际要求的,类型明智),但代价是你不能在上面使用任何东西,除了您指定的约束提供的操作 - 非常不适合这里。

    【讨论】:

    • 哇哦,这正是我在对 newacct 的回答发表评论时所要表达的意思,但我懒得写:)
    • 信息量很大。我最终在我的代码中使用了上面 ehemient 的注释。你的解释对我的理解有很大帮助。 (RWH 尚未涵盖“实例”,但从上下文可以看出它的作用。)非常感谢。
    【解决方案2】:

    这样的?

    data (Num a, Ord a) => Point2 a = Point2 {
        x :: a
      , y :: a
    }
    

    【讨论】:

    • 更常见的是,在数据声明中省略上下文并在实际使用类型的位置使用“(Num a, Ord a) => Point2 a”,但这也有效。
    • 谢谢。这很有效,现在我看到它甚至是有意义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多