Why doesn't equality involving "mod" not typecheck in Idris? - dependent-type

Why won't the following typecheck:
v1 : mod 3 2 = 1
v1 = Refl
Yet this will typecheck fine:
v2 : 3 - 2 = 1
v2 = Refl

It happens due to partiality of mod function (thanks to #AntonTrunov clarification). It's polymorphic and by default numeral constants are Integers.
Idris> :t mod
mod : Integral ty => ty -> ty -> ty
Idris> :t 3
3 : Integer
Idris> :t mod 3 2
mod 3 2 : Integer
For Integer type mod function is not total.
Instead use modNatNZ function so everything type checks perfectly and works.
v1 : modNatNZ 3 2 SIsNotZ = 1
v1 = Refl

Related

Auto implicit arg stops working when type is given a name

While writing this answer, I noticed that while this works as expected:
onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat
onlyModBy5 n = n
foo : Nat
foo = onlyModBy5 25
but as soon as I give a name to the property it stops working:
Divides : Nat -> Nat -> Type
Divides n k = k `modNat` n = 0
onlyModBy5 : (n : Nat) -> {auto prf : 5 `Divides` n} -> Nat
onlyModBy5 n = n
foo : Nat
foo = onlyModBy5 25
now filling the auto arg fails with
Can't find a value of type
Divides 5 25
Why is Idris unable to see through Divides's definition?
I am not sure if this is the reason, but modNat is not total. That would be a good reason to trip idris.
divides : Nat -> Nat -> Nat
divides n k = n `modNat` k
onlyModBy5 : (n : Nat) -> {auto prf : n `divides` 5 = 0 } -> Nat
onlyModBy5 n = n
foo : Nat
foo = onlyModBy5 25
For some reason this already fails as well (just indirecting once from the original version).

Helper Function to Determine if Nat `mod` 5 == 0

Xash provided me with a helpful answer on Function to Determine if Nat is Divisible by 5 at Compile-Time (that I re-named from my original long name):
onlyModBy5 : (n : Nat) -> n `modNat` 5 = 0 -> Nat
onlyModBy5 n prf = n
A previous answer educated me how to run it on the REPL using the Refl argument:
-- 5 % 5 == 0, so it should compile
*Test> onlyModBy5 5 Refl
5 : Nat
-- 7 % 5 == 2, so it should not compile
*Test> onlyModBy5 7 Refl
(input):1:12:When checking an application of function Main.onlyModBy5:
Type mismatch between
x = x (Type of Refl)
and
modNat 7 5 = 0 (Expected type)
Specifically:
Type mismatch between
2
and
0
Then, I tried to define a helper function that would provide the second prf (proof) argument for conciseness. In other words, I'd prefer the caller of this function to not have to provide the Refl argument.
onlyModBy5Short : (n : Nat) -> Nat
onlyModBy5Short n = onlyModBy5 n Refl
But, it does not compile:
When checking right hand side of onlyModBy5Short with expected type
Nat
When checking an application of function Main.onlyModBy5:
Type mismatch between
0 = 0 (Type of Refl)
and
modNat n 5 = 0 (Expected type)
Specifically:
Type mismatch between
0
and
Prelude.Nat.modNatNZ, mod' n 4 SIsNotZ n n 4
Holes: Main.onlyModBy5Short
How, if possible, can this function be written?
You can make onlyModBy5's second argument an auto argument:
onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat
onlyModBy5 n = n
This works because for a given literal value of n, n `modNat` 5 can always be reduced, and so n `modNat` 5 = 0 will always reduce to 0 = 0 (in which case the constructor Refl has the right type) unless n is truly not divisible by 5.
Indeed, this will allow you to typecheck
foo : Nat
foo = onlyModBy5 25
but reject
bar : Nat
bar = onlyModBy5 4

Why doesn't this use of Elem typecheck?

I am quite confused.
module Experiment
import Data.Vect
p1: Elem 5 [3,4,5,6]
p1 = There (There Here)
v : Vect 4 Int
v = 3 :: 4 :: 5 :: 6 :: Nil
p2: Elem 5 v
p2 = There (There Here)
The definition of p2 does not typecheck, while the definition of p1 does. I am using Idris 0.10.2. Is there something I am missing?
Lowercase names in type declarations are interpreted as implicit arguments (like a in length : List a -> Nat which is actually length : {a : Type} -> List a -> Nat). To refer to the defined Vect you can either use an uppercase name or refer by the namespace:
module Experiment
import Data.Vect
A : Vect 4 Int
A = 3 :: 4 :: 5 :: 6 :: Nil
p2: Elem 5 A
p2 = There (There Here)
a : Vect 4 Int
a = 3 :: 4 :: 5 :: 6 :: Nil
p3: Elem 5 Experiment.a
p3 = There (There Here)

How does "There" work in the idris tutorial, page 11, section 3.4.4?

Here is the example from the tutorial, slightly modified for simplicity:
data Vect : Nat -> (b:Type) -> Type where
Nil : Vect Z a
(::) : a -> Vect k a -> Vect (S k) a
data Elem : a -> Vect n a -> Type where
Here : {x:a} -> {xs:Vect n a} -> Elem x (x :: xs)
There : {x,y:a} -> {xs:Vect n a} -> Elem x xs -> Elem x (y :: xs)
testVec : Vect 4 Int
testVec = 3 :: 4 :: 5 :: 6 :: Nil
inVect : Elem 4 testVec
inVect = There Here
I can't understand how There verifies that the value is correct.
As far as I understand it, There works like a function, so it takes the
element of type Here, which when filling in the holes, corresponds to Elem 3 testVec, then sets the first value of testVec to y, and the rest to xs. But since, y isn't used anywhere, I would except this not to cause any restriction.
However, when I try
inVectBroken : Elem 2 testVec
inVectBroken = There Here
I get an error:
When checking an application of constructor There:
Type mismatch between
Elem x (x :: xs) (Type of Here)
and
Elem 2 [4, 5, 6] (Expected type)
Specifically:
Type mismatch between
2
and
4
Can someone explain to me how the above code works (magically?) to restrict There to the tail of Vect?
Here 4 (x :: xs) is a proof that 4 is at the head of (x :: xs), so x = 4. There takes a proof Elem 4 xs that 4 is somewhere in xs and so proofs Elem 4 (y :: xs), that 4 is still somewhere down a extended list. That is where the y goes to. It does not matter what y actually is, it just allows to extend the proof to larger lists. For example:
in1 : Elem 4 (4 :: Nil)
in1 = Here
in2 : Elem 4 (3 :: 4 :: Nil)
in2 = There in1
in3 : Elem 4 (8 :: 4 :: Nil)
in3 = There in1
By the types you see that not the element 4 changes throughout the proof but the list.

Idris Nat literals in types

I'd like Idris to prove that testMult : mult 3 3 = 9 is inhabited.
Unfortunately this is typed as
mult (fromInteger 3) (fromInteger 3) = fromInteger 9 : Type
I can work around it like this:
n3 : Nat; n3 = 3
n9 : Nat; n9 = 9
testMult : mult n3 n3 = n9
testMult = Refl
Is there a way to do something that would be similar to mult (3 : Nat) (3 : Nat) = (9 : Nat)?
You can use the function the : (a : Type) -> a -> a to specify the type when the type inference is failing for you.
testMult : the Nat (3 * 3) = the Nat 9
testMult = Refl
Note that you need to have the at both sides of the equality because Idris has heterogenous equality, that is, (=) : {a : Type} -> {b : Type} -> a -> b -> Type.
Alternatively, you could write
testMult : the Nat 3 * the Nat 3 = the Nat 9
testMult = Refl
If you prefer that style.