我有以下使用 ghcs 扩展的固定长度向量的定义GADTs,TypeOperators并且DataKinds:
data Vec n a where
T :: Vec VZero a
(:.) :: a -> Vec n a -> Vec (VSucc n) a
infixr 3 :.
data VNat = VZero | VSucc VNat -- ... promoting Kind VNat
type T1 = VSucc VZero
type T2 = VSucc T1
以及 TypeOperator 的以下定义:+:
type family (n::VNat) :+ (m::VNat) :: VNat
type instance VZero :+ n = n
type instance VSucc n :+ m = VSucc (n :+ m)
为了使我的整个意图库有意义,我需要将类型的固定长度向量函数(Vec n b)->(Vec m b)应用于较长向量的初始部分Vec (n:+k) b。让我们调用那个函数prefixApp。它应该有类型
prefixApp :: ((Vec n b)->(Vec m b)) -> (Vec (n:+k) b) -> (Vec (m:+k) b)
这是一个示例应用程序,其change2定义如下:
change2 :: Vec T2 a -> Vec T2 a
change2 (x :. y :. T) = (y :. x :. T)
prefixApp应该能够应用于change2任何长度> = 2的向量的前缀,例如
Vector> prefixApp change2 (1 :. 2 :. 3 :. 4:. T)
(2 :. 1 :. 3 :. 4 :. T)
有谁知道如何实施prefixApp?(问题是,必须使用固定长度向量函数类型的一部分来获取正确大小的前缀......)
编辑:Daniel Wagners(非常聪明!)解决方案似乎与 ghc 7.6 的一些候选版本(不是官方版本!)一起使用。恕我直言,它不应该工作,但是,有两个原因:
- for 的类型声明在上下文中
prefixApp缺少一个(用于正确类型检查。VNum mprepend (f b) - 更有问题:ghc 7.4.2 不假设 TypeOperator
:+在其第一个参数中是单射的(也不是第二个,但这里不是必需的),这会导致类型错误:从类型声明中,我们知道vec必须有type并且类型检查器为定义右侧Vec (n:+k) a的表达式推断出. 但是:类型检查器无法推断出这一点(因为没有单射的保证)。split vecVec (n:+k0) ak ~ k0:+
有谁知道第二个问题的解决方案?我怎样才能在它的第一个论点中声明:+是单射的和/或我怎样才能完全避免遇到这个问题?