我正在尝试制作一些Haskell类型,这些类型不是按类型而是按类型的元素进行参数化,特别是整数。例如,R ^ 2中的(线性代数)矢量和R ^ 3中的矢量是不同类型的对象。具体来说,我正在Haskell中编写一个K-D树,我想通过一个正整数参数化我的数据结构,所以三维树和四维树有不同的类型。
我试图通过元组对我的树进行参数化,但它似乎没有去任何地方(并且似乎有点不太可能通过,特别是因为它似乎不是三倍或更大的甚至是仿函数(我不知道怎么说,例如HomogeneousTuple a => Functor a。)我想做这样的事情:
data (TupleOfDoubles a) => KDTree a b = ... ---so in a 3DTree a is (Double,Double,Double)
那会很好,或类似的东西也同样好
data KDTree Int a = ... -- The Int is k, so KDTree has kind Int -> * -> *
有人知道这些影响中的任何一种是否可行或合理吗?
由于 -Joseph
答案 0 :(得分:5)
正在进行一项名为TypeNats的GHC扩展,这正是您想要的。然而,根据the ticket,目前的里程碑设置为7.4.1,所以这还有点等待。
在该扩展可用之前,您唯一能做的就是使用类型对维度进行编码。例如,沿着这些方向的东西可能有效:
{-# LANGUAGE ScopedTypeVariables #-}
class MyTypeNat a where
toInteger :: a -> Integer
data Zero
data Succ a
instance MyTypeNat Zero where
toInteger _ = 0
instance MyTypeNat a => MyTypeNat (Succ a) where
toInteger _ = toInteger (undefined :: a) + 1
data KDTree a b = -- ...
dimension :: forall a b. MyTypeNat a => KDTree a b -> Integer
dimension = toInteger (undefined :: a)
这样的方法的缺点当然是你必须写KDTree (Succ (Succ (Succ Zero))) Foo
而不是KDTree 3 Foo
。
答案 1 :(得分:3)
sepp2k的答案显示了这样做的基本方法。事实上,很多工作已经完成。
类型级数字包
使用自然数的类型级编码(示例)
不幸的是这样的事情:
data KDTree Int a = ...
真的不可能。最终类型(由KDTree
构造)取决于Int的值,这需要一个称为依赖类型的特性。像Agda和Epigram这样的语言支持这一点,但不支持Haskell。