为什么Int不可推广?

时间:2017-10-12 20:54:08

标签: haskell ghc

我希望得到二维或三维点,使得二维点和三维点可以共享代码,但编译器可以区分它们。这是第一次尝试。

C:\Program Files (x86)\MonoGame\v3.0\Assemblies\Windows

到目前为止工作正常。这是一个简化版本:

{-# LANGUAGE DataKinds, GADTs, KindSignatures #-}

data Dimension = D2 | D3
data Point :: Dimension -> * where
  Point :: Dimension -> [Int] -> Point d
origin = Point D2 [0, 0]

这不编译:{{1​​}}。 GHC 7.10.3的The documentation on datatype promotion列出了某种类型可能无法升级的各种原因(例如,如果它已经涉及提升类型),但我不明白为什么它们会排除Int。

(1)为什么会出现这个错误?

作为奖励,

(2)是否有合理的解决方案或替代方法?例如,搜索显示Fixed-Length Vector Types in Haskell,但这似乎过于复杂。

2 个答案:

答案 0 :(得分:7)

Int原则上是可推广的,但实施工作还没有完成。它们在术语级别实现为硬件单词,原始操作实现为C或汇编程序;想要在类型级别使用的每个这样的操作(包括“将此编译时常量转换为Int”!)需要手动提升,据我所知,这还没有完成。

使用数字的标准代数定义 - 例如Peano nats或位列表 - 相反,代数类型可以通过现有实现进行推广。虽然我没有做足够的建议来推荐特定的一个,但是在Hackage的某个地方应该有几个可用的实现。

答案 1 :(得分:7)

虽然我无法解释为什么Int不可推广,但我可以建议使用类似的可推广类型GHC.TypeLits.Nat。您的第二个示例逐字地使用Point'

的定义
import GHC.TypeLits

data Point' :: Nat -> * where
    Point' :: Int -> [Int] -> Point' d

我还建议明确键入origin,否则GHC可能很难推断出类型,因为d中的Point d是幻像类型。