I'm trying to implement Agda's inspect
idiom in Idris, as a possible workaround for this problem, however, it seems when I pattern match on the MkReveal
constructor, the choice of f
is lost and instead becomes a free parameter.
First, the Idris port of inspect
:
%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)
Then how I try to use it:
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
Here, in the hole ?wtf
I would expect the type of eq
to be partition (`elem` selected) elems = ((n ** xs), (k ** ys))
. However, instead, a new implicitly-bound variable f
is brought in scope:
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))
Edited to add: I have discovered that if I manually specify the b
agument to applyInspect
, I can get the desired type for eq
:
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
This results in
eq : partition (\ARG =>
elemBy (\meth, meth =>
Prelude.Nat.Nat implementation of Prelude.Interfaces.Eq, method == meth
meth)
ARG
selected)
elems =
((n ** xs), (k ** ys))
which is what I'd want.
So, maybe a related question could be, how was I supposed to figure this out (there are no yellow highlights like one you'd get in Agda for unsolved metas...), and is there a way to tweak Reveal
or applyInspect
's definitions so that the b
argument is correctly inferred?