我希望得到二维或三维点,使得二维点和三维点可以共享代码,但编译器可以区分它们。这是第一次尝试。
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,但这似乎过于复杂。
答案 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
是幻像类型。