为什么这个 function/constructor 参数变成了一个自由隐式变量?

Why does this function/constructor argument become a free implicit variable?

我正在尝试实现 Agda's inspect idiom in Idris, as a possible workaround for this problem,但是,当我在 MkReveal 构造函数上进行模式匹配时,f 的选择似乎丢失了,而是变成了一个自由参数.

首先是inspect的Idris端口:

%default total

data Reveal : {a : Type} -> {b : a -> Type} -> (f : (x : a) -> b x) -> (x : a) -> (y : b x) -> Type where
  MkReveal : {a : Type} -> {b : a -> Type} -> {f : (x : a) -> b x} -> {x : a} -> {y : b x} -> (f x = y) -> Reveal {b = b} f x y

inspect : {b : a -> Type} -> (f : (x : a) -> b x) -> (x : a) -> Reveal f x (f x)
inspect {b = b} f x = MkReveal {b = b} {f = f} {y = f x} Refl

applyInspect : {b : a -> Type} -> (f : (x : a) -> b x) -> (x : a) -> (y ** Reveal f x y)
applyInspect f x = (f x ** inspect f x)

那我是怎么用的:



foo : (Monad m) => m ()
foo = do
    let selected = the (Vect 2 Nat) $ pure 0
    let elems = the (Vect 9 Nat) $ pure 0

    let (((n ** xs), (k ** ys)) ** MkReveal eq) = 
            applyInspect (partition (`elem` selected)) elems
    ?wtf

在这里,在洞 ?wtf 中,我希望 eq 的类型是 partition (`elem` selected) elems = ((n ** xs), (k ** ys))。然而,取而代之的是,一个新的隐式绑定变量 f 被引入范围:

f : (x : Vect (fromInteger 9) Nat) ->
    (\__pi_arg4 => ((p : Nat ** Vect p Nat), (q : Nat ** Vect q Nat))) x
eq : f elems = ((n ** xs), (k ** ys))

编辑添加: 我发现如果我手动将 b 参数指定为 applyInspect,我可以获得 [=] 所需的类型21=]:

    let (((n ** xs), (k ** ys)) ** MkReveal eq) = 
            applyInspect {b = \_ => (DPair Nat (\p => Vect p Nat), DPair Nat (\q => Vect q Nat))}
                (partition (`elem` selected)) elems

这导致

eq : partition (\ARG =>
                  elemBy (\meth, meth =>
                            Prelude.Nat.Nat implementation of Prelude.Interfaces.Eq, method == meth
                                                                                               meth)
                         ARG
                         selected)
               elems =
     ((n ** xs), (k ** ys))

这就是我想要的。

所以,也许一个相关的问题可能是,我应该如何解决这个问题(没有像 Agda 中未解决的元数据那样的黄色高亮显示。 ..),有没有办法调整RevealapplyInspect的定义,以便正确推断b参数?

原来这个问题的根源是重载:在不知道其具体类型的情况下,partition 的出现在 Prelude.List.partitionData.Vect.partition 之间是不明确的。

将代码更改为

let (((n ** xs), (k ** ys)) ** MkReveal eq) = 
        applyInspect (Data.Vect.partition (`elem` selected)) elems

将正确的类型分配给 eq

此外,事实证明整个 Reveal 机器并没有提供太多,即我可以用更简单的

做所有事情
inspect : {b : a -> Type} -> (f : (x : a) -> b x) -> (x : a) -> (y ** (f x = y))
inspect f x = (f x ** Refl)