在Haskell数据类型中键入类

Gre*_*ski 15 haskell types typeclass

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

data Point1 = Point1 {
    x :: Integer
  , y :: Integer
}
Run Code Online (Sandbox Code Playgroud)

可以在数据类型中为变量使用类型类吗?如果是这样的话?我意识到有可能将它作为代数数据类型,对每种点都有不同的定义,但我想知道是否有办法以更紧凑和灵活的方式实现这一点.

例如,使用函数声明语法的伪代码行:

data Point2 = Point2 {
    x :: (Num a, Ord a) => a
  , y :: (Num a, Ord a) => a
}
Run Code Online (Sandbox Code Playgroud)

目标是允许在数据类型中存储Int,Integer,FloatDouble值.理想情况下,我想限制它,以便x和y必须是相同的类型.

Edw*_*ETT 19

您需要决定是否要对该类型进行存在性或通用量化.通用量化,ala:

data (Num a, Ord a) => Point2 a = Point2 a a
Run Code Online (Sandbox Code Playgroud)

产生了一个证明义务,Num和Ord实例存在于类型'a'但实际上并没有那么多帮助,因为当你通过构造该类型的值来使用Point类时,它所做的就是给你一个义务或者当你去模式匹配它.

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

data Point2 a = Point2 a a deriving (Eq,Ord,Show,Read)
Run Code Online (Sandbox Code Playgroud)

并使您的每个实例都取决于您想要的额外信息.

instance Num a => Num (Point2 a) where
    ...

instance (Num a, Ord a) => SomeClass (Point2 a) where
    ...
Run Code Online (Sandbox Code Playgroud)

这使您可以传递并构建更少的多余字典,并增加可以使用Point2数据类型的方案的数量.

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

  • 哇哇,这正是我在对newacct答案的评论中所得到的,但是太懒了,不能写:) (2认同)

new*_*cct 7

这样的事情?

data (Num a, Ord a) => Point2 a = Point2 {
    x :: a
  , y :: a
}
Run Code Online (Sandbox Code Playgroud)

  • 更常见的情况是,在数据声明中保留上下文,并在实际使用类型的位置使用"(Num a,Ord a)=> Point2 a",但这也有效. (8认同)
  • 这不是ghc 7.4.1的合法haskel代码 (3认同)