Haskell 为编译器提供无模式匹配的证明

Haskell 为编译器提供无模式匹配的证明,haskell,dependent-type,Haskell,Dependent Type,假设我有一个证据: -- (pseudocode) m and n are natural numbers proof :: forall m n. (1 <= m, m < n) => SNat n -> SNat m -> (1 <= n - 1) proof _ _ = unsafeCoerce Refl 但是proof适用于任何n和m,因此在运行时总是进行不必要的模式匹配。如何避免这种情况 编辑用例: -- 0 1

假设我有一个证据:

-- (pseudocode) m and n are natural numbers
proof :: forall m n. (1 <= m, m < n) => SNat n -> SNat m -> (1 <= n - 1)
proof _ _ = unsafeCoerce Refl
但是
proof
适用于任何
n
m
,因此在运行时总是进行不必要的模式匹配。如何避免这种情况

编辑用例:

--                  0 1 2 3 4 ... n-1
--returns Vec n a : 1 0 0 0 0 ... 0
helper :: (UVec a, Num a) => SNat n -> Vec n a
helper n = case isZero n of
  NonZero -> 1 `vcons` vpreplicate (sPred n) 0
  Zero -> vnil

proof1 :: forall n m . (CmpNat n m ~ GT) => SNat n -> SNat m -> ((CmpNat (n :- 1) (m :- 1)) :~: GT)
proof1 n m = unsafeCoerce Refl

proof2 :: forall n m . (1 <= m, (CmpNat n m) ~ GT) => SNat n -> SNat m -> ((1 <=? (n :- 1)) :~: True)
proof2 n m = unsafeCoerce Refl

--                  0 1 2 ... m . . . . . . n-1
--returns Vec n a : 0 0 0 ... 1 0 0 0 0 ... 0
helper2 :: forall a m n.(UVec a, Num a, 1 <= n, (CmpNat n m) ~ GT) => SNat n -> SNat m -> Vec n a
helper2 size m = case (isZero m, proof1 size m) of
  (NonZero, Refl) ->
    case (proof2 size m) of
      Refl -> (0 :: a) `vcons` helper2 (sPred size) (sPred m)

  (Zero,_) -> helper size
--0 1 2 3 4。。。n-1
--返回向量n a:1 0 0。。。0
助手::(UVec a,Num a)=>SNat n->Vec n a
helper n=大小写为零n
非零->1`vcons`vpreplicate(sPred n)0
零->vnil
证明1::对于所有n m。(CmpNat n m~GT)=>SNat n->SNat m->(CmpNat(n:-1)(m:-1)):~:GT)
证明1 n m=不安全的反射
证明2::对于所有n m。(1 SNat n->SNat m->)((1 SNat m->Vec n a
helper2 size m=的大小写(为零m,校对1 size m)
(非零,Refl)->
箱子(尺寸为2米)
Refl->(0::a)`vcons`helper2(sPred大小)(sPred m)
(零,824;)->辅助对象大小

如果假定经常使用
helper2
,则额外的模式匹配会增加开销。

请展示完整的用例以及困扰您的问题。如果证据是内联的,编译器可能会对其进行优化。无论如何,它是O(1)匹配,因此即使没有优化,也不会花费很多成本。(不过要小心,因为强制证明很容易违反类型安全。)我认为优化证明的标准技巧是实际进行证明(因此不要将
未安全的Refl
作为
证明的主体),然后添加一个重写
规则
来优化
proof x y
unsafeccerce Refl
中。这样,当您的代码在没有优化的情况下编译时,您可以“运行”您的证明,而当您的代码在经过优化的情况下编译时,则不会运行它们。参考(至少,这是我第一次听说它的地方)对于@Alec的建议:您的代码所依赖的导入/定义是什么?请发布一个。至于“免费”强制,请考虑引入
--                  0 1 2 3 4 ... n-1
--returns Vec n a : 1 0 0 0 0 ... 0
helper :: (UVec a, Num a) => SNat n -> Vec n a
helper n = case isZero n of
  NonZero -> 1 `vcons` vpreplicate (sPred n) 0
  Zero -> vnil

proof1 :: forall n m . (CmpNat n m ~ GT) => SNat n -> SNat m -> ((CmpNat (n :- 1) (m :- 1)) :~: GT)
proof1 n m = unsafeCoerce Refl

proof2 :: forall n m . (1 <= m, (CmpNat n m) ~ GT) => SNat n -> SNat m -> ((1 <=? (n :- 1)) :~: True)
proof2 n m = unsafeCoerce Refl

--                  0 1 2 ... m . . . . . . n-1
--returns Vec n a : 0 0 0 ... 1 0 0 0 0 ... 0
helper2 :: forall a m n.(UVec a, Num a, 1 <= n, (CmpNat n m) ~ GT) => SNat n -> SNat m -> Vec n a
helper2 size m = case (isZero m, proof1 size m) of
  (NonZero, Refl) ->
    case (proof2 size m) of
      Refl -> (0 :: a) `vcons` helper2 (sPred size) (sPred m)

  (Zero,_) -> helper size