Say I'd like to define a type of a proof that some vector has a certain sum. I'd also like that proof to work for any Monoid
type t
. My first attempt was this:
data HasSum : Monoid t => t -> Vect n t -> Type where
EndNeutral : Monoid t => HasSum Prelude.Algebra.neutral []
Component : Monoid t => (x : t) -> HasSum sum xs -> HasSum (x <+> sum) (x :: xs)
Unfortunately, the compiler argues it Can't find implementation for Monoid t
. So I tried with an implicit argument so that I can specify its type:
EndNeutral : Monoid t => {Prelude.Algebra.neutral : t} -> HasSum Prelude.Algebra.neutral []
This compiles, but this does not:
x : HasSum 0 []
x = EndNeutral
strangely claiming that it Can't find implementation for Monoid Integer
.
My final attempt was to define a helper constant with capital letter name so that Idris doesn't confuse it for a bound variable:
ZERO : Monoid t => t
ZERO = neutral
data HasSum : Monoid t => t -> Vect n t -> Type where
EndNeutral : Monoid t => HasSum ZERO []
Component : Monoid t => {rem : t} -> (x : t) -> HasSum rem xs -> HasSum (x <+> rem) (x :: xs)
but now it can't guess the type of ZERO
in the definition of EndNeutral
(Can't find implementation for Monoid t
). So I tried again with an implicit binding:
EndNeutral : Monoid t => {ZERO : t} -> HasSum ZERO []
but now ZERO
becomes a bound variable and although it compiles, it does not work as expected, because it allows to construct a proof of empty vectory having an arbitrary sum.
At this point I ran out of ideas. Does anyone know how to express a polymorphic constant in an Idris type?