有没有办法说服GHC这个(单射)类型族是单射的?

时间:2018-01-14 15:21:04

标签: haskell type-families data-kinds

使用GHC的DataKinds,我尝试实现类型级二进制nat。它们很容易实现,但如果我希望它们在常见情况下有用,那么GHC需要相信Succ类型族是单射的(因此类型推断至少与它一样有效)对于一元类型级别的nats)。但是,我很难说服GHC这是事实。考虑以下二进制nat编码:

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilyDependencies #-}
module Nat2 where

data Nat = Zero | Pos Nat1
data Nat1 = One | Bit0 Nat1 | Bit1 Nat1
  -- by separating Nat and Nat1 we avoid dealing w/ Bit0^n Zero as a spurrious representation of 0

type family Succ (n :: Nat) :: r | r -> n where
  Succ 'Zero = 'Pos 'One
  Succ ('Pos x) = 'Pos (Succ1 x)

type family Succ1 (n :: Nat1) :: r | r -> n where
  Succ1 'One = 'Bit0 'One
  Succ1 ('Bit0 x) = 'Bit1 x
  Succ1 ('Bit1 x) = 'Bit0 (Succ1 x)

GHC不能接受这一点,因为它无法判断Succ1是否是单射的:

Nat2.hs:12:3: error:
    • Type family equations violate injectivity annotation:
        Succ 'Zero = 'Pos 'One -- Defined at Nat2.hs:12:3
        Succ ('Pos x) = 'Pos (Succ1 x) -- Defined at Nat2.hs:13:3
    • In the equations for closed type family ‘Succ’
      In the type family declaration for ‘Succ’
   |
12 |   Succ 'Zero = 'Pos 'One
   |   ^^^^^^^^^^^^^^^^^^^^^^

Nat2.hs:16:3: error:
    • Type family equations violate injectivity annotation:
        Succ1 'One = 'Bit0 'One -- Defined at Nat2.hs:16:3
        Succ1 ('Bit1 x) = 'Bit0 (Succ1 x) -- Defined at Nat2.hs:18:3
    • In the equations for closed type family ‘Succ1’
      In the type family declaration for ‘Succ1’
   |
16 |   Succ1 'One = 'Bit0 'One
   |   ^^^^^^^^^^^^^^^^^^^^^^^

我们认为它是单射的,因为通过检查Succ1One永远不在其图像中,因此Bit0 (Succ1 x)案例永远不会返回Bit0 One因此,Bit1案例永远不会与One案件发生冲突。相同的参数(“One”的图像中没有“Succ1”)表明Succ本身也是单射的。然而,GHC并不十分聪明,无法找到这个论点。

所以,问题:在这种情况下(和这些情况一样),有没有办法说服GHC一个内射型家族实际上是单射的? (也许是一个typechecker插件,我可以在其中提供一个反转Succ1的函数?也许是一个pragma,上面写着“尝试从这个家族向后推断,好像它是单射的;如果你遇到任何歧义,你就可以崩溃”?)

0 个答案:

没有答案