为什么这个 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 中未解决的元数据那样的黄色高亮显示。 ..),有没有办法调整Reveal
或applyInspect
的定义,以便正确推断b
参数?
原来这个问题的根源是重载:在不知道其具体类型的情况下,partition
的出现在 Prelude.List.partition
和 Data.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)
我正在尝试实现 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 中未解决的元数据那样的黄色高亮显示。 ..),有没有办法调整Reveal
或applyInspect
的定义,以便正确推断b
参数?
原来这个问题的根源是重载:在不知道其具体类型的情况下,partition
的出现在 Prelude.List.partition
和 Data.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)