在Haskell

时间:2015-04-22 21:15:30

标签: haskell ghc type-level-computation

为了处理某些网络协议,我一直在使用GHC.TypeLits来实现固定大小的位向量作为用Nat类型标记的包裹整数。

newtype W (n :: Nat) = W { getW :: Integer }

除了各种类(Integral,Num,Bits等)的实例外,我还定义了一个函数来组合它们:

(>+<) :: forall n m. (KnownNat m, KnownNat n, KnownNat (m + n)) => W m -> W n -> W (m + n)
(W x) >+< (W y) = fromInteger $ x + shift y (natValInt (Proxy :: Proxy m))

下一部分是我遇到麻烦的地方。我正在尝试创建一个导致W n的应用,导致W m,其中mn的除数。例如,使用attoparsec,应该能够写:

anyWord128 :: Parser (W 128)
anyWord128 = assemble $ fmap (fromIntegral :: Word8 -> W 8) anyWord8

这是我的尝试:

class (KnownNat d, KnownNat n) => d :|: n where
    assemble :: forall f. Applicative f -> f (W d) -> f (W n)

instance KnownNat n => n :|: n where
    assemble = id

instance (KnownNat n, CmpNat n d ~ GT, d :|: n', (d + n') ~ n) => d :|: n where
    assemble f = liftA2 (>+<) f (assemble f)

代码编译(包含许多语言扩展,包括-XOverlappingInstances,所有这些都在下面链接的实际源中),加载assemble的示例用法会导致GHCi告诉我{的实例重叠{1}}。我猜这是因为我不知道自己在做什么,或者因为GHC的类型检查程序的计算能力有限(或两者兼而有之)。

你们中的任何一个GHC向导都能看到正确定义这个类的方法吗?

修改

固定类型的汇编定义 - 谢谢kosmikus 此外,这里是完整的source(第{159行)定义了8 :|: 8

0 个答案:

没有答案