使用Type Nats创建类型级别列表(在类型级别添加数字时出现问题)

时间:2012-12-16 03:25:21

标签: haskell types

为了好玩,我想创建一个知道它有多长的类型级别列表。像这样:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import GHC.TypeLits

data family TypeList a (n::Nat)

data instance TypeList a (0) = EmptyList
data instance TypeList a (1) = TL1 a (TypeList a (0))
data instance TypeList a (2) = TL2 a (TypeList a (1))
data instance TypeList a (3) = TL3 a (TypeList a (2))

但是,我当然希望将其概括为:

data instance TypeList a (n)   = TL3 a (TypeList a (n-1))

但这会产生错误:

    TypeList.hs:15:53: parse error on input `-'
    Failed, modules loaded: none.

另一次尝试:

data instance TypeList a (n+1) = TL3 a (TypeList a (n))

还会生成错误:

    Illegal type synonym family application in instance: n + 1
    In the data instance declaration for `TypeList'

我认为这样的事情必须是可能的。使用符号肯定是可能的:

data Zero
data Succ a

但我无法用更好看的版本弄明白。

2 个答案:

答案 0 :(得分:6)

类型级别Nat的改进落在GHC 7.8中,现在可以实现!

{-# LANGUAGE DataKinds, KindSignatures #-}
{-# LANGUAGE TypeFamilies, TypeOperators #-}

import GHC.TypeLits

data family List (n :: Nat) a
data instance List 0 a = Nil
data instance List n a = a ::: List (n - 1) a

infixr 8 :::

使用List与任何[]一样自然 - 就像您自己编写的数据结构一样:

λ. :t 'a' ::: 'b' ::: 'c' ::: Nil
'a' ::: 'b' ::: 'c' ::: Nil :: List 3 Char

答案 1 :(得分:3)

正如他们在GHC 7.6中一样,类型级Nats不会让你做这类事情。目前,0 :: Nat1 :: Nat类型之间或多或少没有关系,尽管名称提示(与您的ZeroSucc Zero不同,您可以使用它们的事情)。这在GHC的未来版本中会更好。