GHC 7.8中类型级自然的行为

时间:2014-05-14 21:19:48

标签: haskell types type-level-computation

如果你想要按长度索引的矢量,你可以这样做:

{-# LANGUAGE 
  DataKinds, GADTs, TypeOperators, TypeFamilies, StandaloneDeriving
  #-}

data N = P N | Z 

type family Add (n :: N) (m :: N) :: N
type instance Add Z     a = a
type instance Add (P a) b = P (Add a b)

infixr 5 :>
data Vect n a where 
  V0   :: Vect Z a
  (:>) :: a -> Vect n a -> Vect (P n) a

deriving instance Show a => Show (Vect n a)

concatV :: Vect n a -> Vect m a -> Vect (Add n m) a
concatV V0 y = y
concatV (x :> xs) y = x :> concatV xs y

在ghc 7.8中,我希望新的type literals会过时,但直接转换无效:

{-# LANGUAGE 
  DataKinds, GADTs, TypeOperators, TypeFamilies, StandaloneDeriving
  #-}

import GHC.TypeLits 

infixr 5 :>
data Vect (n :: Nat) a where 
  V0   :: Vect 0 a
  (:>) :: a -> Vect n a -> Vect (n+1) a

deriving instance Show a => Show (Vect n a)

concatV :: Vect n a -> Vect m a -> Vect (n + m) a
concatV V0 y = y
concatV (x :> xs) y = x :> concatV xs y

Unfortunatley这给出了一个错误:NB: +'是一个类型函数,可能不是单射的。我明白为什么会发生这种情况,但是因为类型文字无论如何都是编译器魔法,我不知道为什么编译器也不能将它魔术化。

我尝试更改Vect(:>) :: a -> Vect (n-1) a -> Vect n a。这种方式有一个内部向量的显式公式,但这给出了错误:

Couldn't match type `(n + m) - 1' with `(n - 1) + m'
Expected type: Vect ((n + m) - 1) a
  Actual type: Vect ((n - 1) + m) a

所以现在它需要基本算术的证明。我无法使任何一个版本工作。有没有办法为编译器编写(n + m) - o == (n - o) + m证明,或以某种方式使第一个版本工作?

2 个答案:

答案 0 :(得分:6)

类型级自然仍然没有真正做计算。 GHC 7.10预计将集成SMT求解器,最终处理您认为应该能够实现的所有内容。

作为一个理论上不合理但却可以回答你实际问题的答案 - 当你知道两个表达式具有相同的类型但编译器没有相同的情况时,unsafeCoerce存在。

答案 1 :(得分:2)

GHC 7.8解算器仍然无法解决与自然类型有很多算术关系的问题。虽然在这种情况下使用unsafeCoerce迫使GHC识别预期类型是完全安全的。

{-# LANGUAGE
  DataKinds, GADTs, TypeOperators, TypeFamilies, StandaloneDeriving
  #-}

import GHC.TypeLits
import Unsafe.Coerce

infixr 5 :>
data Vect (n :: Nat) a where
  V0   :: Vect 0 a
  (:>) :: a -> Vect n a -> Vect (n+1) a

deriving instance Show a => Show (Vect n a)

concatV :: Vect n a -> Vect m a -> Vect (n + m) a
concatV V0 y        = unsafeCoerce y
concatV (x :> xs) y = unsafeCoerce $ x :> concatV xs y