You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用with子句匹配Vect末尾元素时报Not a constructor application or primitive错误

问题说明

你尝试实现基于视图的Vect末尾n个元素模式匹配,已有定义如下:

data SplitLast : (n : Nat) -> (xs : Vect r a)
                 -> {auto prf : n `LTE` r} -> Type where
  Append : forall m, n . (init : Vect m a) -> (tail : Vect n a)
  -> SplitLast {prf=rewrite plusCommutative m n in lteAddRight n} n (init ++ tail)

splitLast : (n : Nat) -> (xs : Vect r a)
            -> {auto prf : n `LTE` r} -> SplitLast n xs

上述代码可正常编译,但在with子句中使用该视图时出现报错:

flipLast : Vect (S (S r)) Nat -> Vect (S (S r)) Nat
flipLast xs with (splitLast 2 xs)
  flipLast (leading ++ [m, n]) | (Append leading [m, n]) = leading ++ [n, m]

报错信息:

While processing left hand side of with block in flipLast. Can't match
on ?postpone [no locals in scope] (Not a constructor application or primitive).
...
187 | flipLast (leading ++ [m, n]) | (Append leading [m, n]) = leading ++ [n, m]
^^

报错原因
  • 模式匹配的左侧仅支持构造器表达式,++是Vect的拼接函数,不属于构造器(Vect的构造器仅为::和Nil),编译器无法反向将输入的xs拆解为leading ++ [m, n]的形式,因此抛出匹配失败错误。
  • 你的SplitLast视图本身已经完成了Vect的拆分逻辑,Append构造器返回的init和tail就是拆分完成的前后段,无需在原参数位置重复做拼接匹配。
修复方案

直接使用视图返回的拆分结果即可,无需对原参数做拼接模式匹配:

flipLast : Vect (S (S r)) Nat -> Vect (S (S r)) Nat
flipLast xs with (splitLast 2 xs)
  flipLast _ | (Append leading [m, n]) = leading ++ [n, m]

如果存在隐式证明合一的问题,也可以简化SplitLast的定义,将证明逻辑完全封装在splitLast的实现中,避免构造器内的rewrite影响类型推断:

data SplitLast : (n : Nat) -> (xs : Vect r a) -> {auto prf : n `LTE` r} -> Type where
  Append : (init : Vect m a) -> (tail : Vect n a) -> SplitLast n (init ++ tail)

内容的提问来源于stack exchange,提问作者joel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:06:01