I'm experimenting with Idris and I had the idea to create a type that represented a valid reference to a subdivision of an array.
So for example, if the array has a size of 100 and I want my subdivisions to be of size 20, the type would ensure that you could not construct a value that referred to subdivision number 7. Here is what I came up with:
data Loc : Nat -> Nat -> Type where
MkLoc
: (t : Nat)
-> (p : Nat)
-> {auto pNZ : NonZero p}
-> {auto tGTEp : t `GTE` p}
-> (i : Fin (divCeilNZ t p pNZ))
-> Loc t p
But when I try to construct a value of this type I get an error:
Main> MkLoc 100 20 0
Error: Can't find an implementation for So (with block in integerLessThanNat 0 False (divCeilNZ 100 20 SIsNonZero)).
I tried something even simpler and still got an error:
Main> the (Fin $ divCeilNZ 100 20 SIsNonZero) 0
Error: Can't find an implementation for So (with block in integerLessThanNat 0 False (divCeilNZ 100 20 SIsNonZero)).
I don't totally understand the error message. It seems like the compiler can't prove that 0 is of type Fin (divCeilNZ t p pNZ)
. But why not? If divCeilNZ
is total shouldn't it get computed at compile-time?
How can I get this to work?