在Haskell中按整数参数化类型

时间:2011-09-01 07:07:31

标签: haskell kdtree algebraic-data-types higher-kinded-types

我正在尝试制作一些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

2 个答案:

答案 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。