Idris: function works with Nat parameter and fails type checking with Integer parameter - idris

I am new to Idris. I am experimenting with types and my task is to make an "onion": a function that takes two arguments: a number and whatever and puts whatever into List nested such number of times.
For example, the result for mkOnion 3 "Hello World" should be [[["Hello World"]]].
I've made such a function, this is my code:
onionListType : Nat -> Type -> Type
onionListType Z b = b
onionListType (S a) b = onionListType a (List b)
mkOnionList : (x : Nat) -> y -> onionListType x y
mkOnionList Z a = a
mkOnionList (S n) a = mkOnionList n [a]
prn : (Show a) => a -> IO ();
prn a = putStrLn $ show a;
main : IO()
main = do
prn $ mkOnionList 3 4
prn $ mkOnionList 2 'a'
prn $ mkOnionList 5 "Hello"
prn $ mkOnionList 0 3.14
The result of program work:
[[[4]]]
[['a']]
[[[[["Hello"]]]]]
3.14
This is exactly what I need.
But when I do the same, but change Nat to Integer like this
onionListTypeI : Integer -> Type -> Type
onionListTypeI 0 b = b
onionListTypeI a b = onionListTypeI (a-1) (List b)
mkOnionListI : (x : Integer) -> y -> onionListTypeI x y
mkOnionListI 0 a = a
mkOnionListI n a = mkOnionListI (n-1) [a]
I get an error:
When checking right hand side of mkOnionListI with expected type
onionListTypeI 0 y
Type mismatch between
y (Type of a) and
onionListTypeI 0 y (Expected type)
Why does type checking fails?
I think this is because Integer can take negative values and Type can't be computed in case of negative values. If I am right, how does the compiler understand this?

You are right, that the type can't be computed. But that is because the onionListTypeI is not total. You can check this in the REPL
*test> :total onionListTypeI
Main.onionListTypeI is possibly not total due to recursive path:
Main.onionListTypeI, Main.onionListTypeI
(Or even better, demanding %default total in the source code, which would raise an error.)
Because the type constructor is not total, the compiler won't normalize onionListTypeI 0 y to y. It is not total, because of the case onionListTypeI a b = onionListTypeI (a-1) (List b). The compiler does only know that subtracting 1 from an Integer results to an Integer, but not which number exactly (unlike when doing it with a Nat). This is because arithmetic with Integer, Int, Double and the various Bits are defined with primary functions like prim__subBigInt. And if these functions wouldn't be blind, the compiler should have a problem with negative values, like you assumed.

Related

How can I create a value of type Fin (divCeilNZ n m p)?

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?

Why I can't use matched variable instead of a variable value?

Here is an example from here. The code looks like that:
sum : (single : Bool) -> isSingleton single -> Nat
sum True x = x
sum False [] = 0
sum False (x :: xs) = x + sum False xs
I've tried to use single instead of False in the last line. But it fails. I think the problem is that the type of sum single xs is either Nat or List Nat, but + requires only Nat operands. But we are inside a clause where single equals False either way. Shouldn't Idris infer it? Why I can't use single here? Is there some reason for it?
Here is the error:
main.idr:14:23-41:
|
14 | sum False (x :: xs) = x + (sum single xs)
| ~~~~~~~~~~~~~~~~~~~
When checking right hand side of Main.sum with expected type
Nat
When checking argument single to Main.sum:
No such variable single
Upd:
It looks like that the problem here is that I can't directly access the variable from type definition. Then I've tried to use implicit arguments like that:
sum : (single : Bool) -> isSingleton single -> Nat
sum True x = x
sum False [] = 0
sum {single} False (x :: xs) = x + sum single xs
It doesn't help either. Maybe I'm using it wrong. Also I've tried the simplest possible variation like that:
sum : (single: Bool) -> isSingleton single -> Nat
sum s list = case s of
True => list
False => case list of
[] => 0
(x::xs) => x + (sum s xs)
But it doesn't compile either:
|
16 | (x::xs) => x + (sum s xs)
| ~~~~~~~~
When checking right hand side of Main.case block in case block in sum at main.idr:12:19 at main.idr:14:19-22 with expected type
Nat
When checking an application of Main.sum:
Type mismatch between
List Nat (Type of xs)
and
isSingleton s (Expected type)
It looks a bit weird for me, because from one point Idris could prove many interesting and complex things, and from another such a simple thins is unavailable. Or maybe I'm doing it wrong.
It's not so much that it can't infer the type of single, as single isn't in scope on the RHS. You could use a named pattern with single on the LHS
sum : (single : Bool) -> isSingleton single -> Nat
sum True x = x
sum False [] = 0
sum single#False (x :: xs) = x + sum single xs
I can't see a way to avoid the named pattern in this case and just use
sum single (x :: xs) = x + sum single xs
as Idris doesn't infer it's a List Nat without the False. I get
|
8 | sum single (x :: xs) = x + sum single xs
| ~~~~~~~~~~~~~~~~~~~~
When checking left hand side of Main.sum:
When checking an application of Main.sum:
Can't disambiguate since no name has a suitable type:
Prelude.List.::, Prelude.Stream.::

How can I describe this property of divisibility in Idris?

I want to prove that if b (Integer) divides a (Integer), then b also divides a * c (where c is an Integer). First, I need to reformulate the problem into a computer understandable problem, here was an attempt:
-- If a is divisible by b, then there exists an integer such that a = b * n
divisibleBy : (a, b : Integer) ->
(n : Integer **
(a = b * n))
-- If b | a then b | ac.
alsoDividesMultiples : (a, b, c : Integer) ->
(divisibleBy a b) ->
(divisibleBy (a * c) b)
However, I am getting TypeUnification failure. I am not really sure what is wrong.
|
7 | alsoDividesMultiples : (a, b, c : Integer) ->
| ^
When checking type of Numbris.Divisibility.alsoDividesMultiples:
Type mismatch between
(n : Integer ** a = b * n) (Type of divisibleBy a b)
and
Type (Expected type)
Specifically:
Type mismatch between
(n : Integer ** a = prim__mulBigInt b n)
and
TypeUnification failure
In context:
a : Integer
b : Integer
c : Integer
{a_509} : Integer
{b_510} : Integer
In Idris, propositions are represented by types, while proofs of propositions are represented by elements of those types. The basic issue here is that you have defined divisibleBy as a function which returns an element (i.e. a proof) rather than a type (proposition). Thus, as you've defined it here, divisbleBy actually purports to be a proof that all integers are divisible by all other integers, which is clearly not true! I think what you're actually looking for is something like this.
DivisibleBy : Integer -> Integer -> Type
DivisibleBy a b = (n : Integer ** a = b * n)
alsoDividesMultiples : (a, b, c : Integer) ->
DivisibleBy a b ->
DivisibleBy (a * c) b

How do you operate on dependent pairs in a proof?

This is a follow up to this question. Thanks to Kwartz I now have a state of the proposition if b divides a then b divides a * c for any integer c, namely:
alsoDividesMultiples : (a, b, c : Integer) ->
DivisibleBy a b ->
DivisibleBy (a * c) b
Now, the goal has been to prove that statement. I realized that I do not understand how to operate on dependent pairs. I tried a simpler problem, which was show that every number is divisible by 1. After a shameful amount of thought on it, I thought I had come up with a solution:
-- All numbers are divisible by 1.
DivisibleBy a 1 = let n = a in
(n : Integer ** a = 1 * n)
This compiles, but I was had doubts it was valid. To verify that I was wrong, it changed it slightly to:
-- All numbers are divisible by 1.
DivisibleBy a 1 = let n = a in
(n : Integer ** a = 2 * n)
This also compiles, which means my "English" interpretation is certainly incorrect, for I would interpret this as "All numbers are divisible by one since every number is two times another integer". Thus, I am not entirely sure what I am demonstrating with that statement. So, I went back and tried a more conventional way of stating the problem:
oneDividesAll : (a : Integer) ->
(DivisibleBy a 1)
oneDividesAll a = ?sorry
For the implementation of oneDividesAll I am not really sure how to "inject" the fact that (n = a). For example, I would write (in English) this proof as:
We wish to show that 1 | a. If so, it follows that a = 1 * n for some n. Let n = a, then a = a * 1, which is true by identity.
I am not sure how to really say: "Consider when n = a". From my understanding, the rewrite tactic requires a proof that n = a.
I tried adapting my fallacious proof:
oneDividesAll : (a : Integer) ->
(DivisibleBy a 1)
oneDividesAll a = let n = a in (n : Integer ** a = b * n)
But this gives:
|
12 | oneDividesAll a = let n = a in (n : Integer ** a = b * n)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When checking right hand side of oneDividesAll with expected type
DivisibleBy a 1
Type mismatch between
Type (Type of DPair a P)
and
(n : Integer ** a = prim__mulBigInt 1 n) (Expected type)
Any help/hints would be appreciated.
First off, if you want to prove properties on number, you should use Nat (or other inductive types). Integer uses primitives that the argument can't argue further than prim__mulBigInt : Integer -> Integer -> Integer; that you pass two Integer to get one. The compiler doesn't know anything how the resulting Integer looks like, so it cannot prove stuff about it.
So I'll go along with Nat:
DivisibleBy : Nat -> Nat -> Type
DivisibleBy a b = (n : Nat ** a = b * n)
Again, this is a proposition, not a proof. DivisibleBy 6 0 is a valid type, but you won't find a proof : Divisible 6 0. So you were right with
oneDividesAll : (a : Nat) ->
(DivisibleBy a 1)
oneDividesAll a = ?sorry
With that, you could generate proofs of the form oneDividesAll a : DivisibleBy a 1. So, what comes into the hole ?sorry? :t sorry gives us sorry : (n : Nat ** a = plus n 0) (which is just DivisibleBy a 1 resolved as far as Idris can). You got confused on the right part of the pair: x = y is a type, but now we need a value – that's what's your last error cryptic error message hints at). = has only one constructor, Refl : x = x. So we need to get both sides of the equality to the same value, so the result looks something like (n ** Refl).
As you thought, we need to set n to a:
oneDividesAll a = (a ** ?hole)
For the needed rewrite tactic we check out :search plus a 0 = a, and see plusZeroRightNeutral has the right type.
oneDividesAll a = (a ** rewrite plusZeroRightNeutral a in ?hole)
Now :t hole gives us hole : a = a so we can just auto-complete to Refl:
oneDividesAll a = (a ** rewrite plusZeroRightNeutral a in Refl)
A good tutorial on theorem proving (where it's also explained why plus a Z does not reduce) is in the Idris Doc.

What does this function do , Haskell

I need an algorithm that converts bin to dec
I found the following code in the Internet , but I just do not know , what some variables mean:
bin2dec :: [Int] -> Int
bin2dec n = foldl (\a x->2*a+x) 0 n
I already know foldl
But what means (\a x->2*a+x) 0 n
I do not know what \a x -> 2*a+x means and also " 0 n"
Could anyone please explain me how this function works ?
Thanks
foldl :: (a -> b -> a) -> a -> [b] -> a
So basically a is first 0 and then the value that is carried throughout the fold. n is the list you pass into bin2dec and 0 is the object you start your fold on.
\a x -> 2 * a + x is a lamda function. It takes two variables, a and x and returns the value given on the right side of the arrow.