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

Mik*_*cki 4 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))
Run Code Online (Sandbox Code Playgroud)

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

data instance TypeList a (n)   = TL3 a (TypeList a (n-1))
Run Code Online (Sandbox Code Playgroud)

但这会产生错误:

    TypeList.hs:15:53: parse error on input `-'
    Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

另一种尝试:

data instance TypeList a (n+1) = TL3 a (TypeList a (n))
Run Code Online (Sandbox Code Playgroud)

还会生成错误:

    Illegal type synonym family application in instance: n + 1
    In the data instance declaration for `TypeList'
Run Code Online (Sandbox Code Playgroud)

我认为这样的事情一定是可能的.使用符号肯定是可能的:

data Zero
data Succ a
Run Code Online (Sandbox Code Playgroud)

但我无法用更好看的版本搞清楚.

cdk*_*cdk 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 :::
Run Code Online (Sandbox Code Playgroud)

使用List就像[]你自己编写的任何类似的数据结构一样自然:

?. :t 'a' ::: 'b' ::: 'c' ::: Nil
'a' ::: 'b' ::: 'c' ::: Nil :: List 3 Char
Run Code Online (Sandbox Code Playgroud)

  • 当我试图在7.8中使用类型级别的"Nat"时,我遇到的问题是它现在适用于固定的有限Nats(例如它可以解决`List(0 +(1 +(1)当你尝试编写像`<++> :: List na - > List ma - > List(n + m)a`这样的通用操作时,你得到的错误就像``List 3 Char`)不能从上下文(n~(n1 + 1))`中推导出(((n1 + m)+ 1)〜(n + m)).因此,在真正取代基于Zero/Succ的方法之前,似乎还需要做更多的工作 - 尽管我远非专家,所以也许我错过了一些东西. (3认同)