Idris: Proving some contradiction cases - proof

I am new to Idris and Proofs in general but I am progressing through Software Foundations ported to Idris. I am working on an exercise
namespace Booleans
data Bool = True | False
andb : Booleans.Bool -> Booleans.Bool -> Booleans.Bool
andb True b = b
andb False _ = False
orb : Booleans.Bool -> Booleans.Bool -> Booleans.Bool
orb True _ = True
orb False b = b
(&&) : Booleans.Bool -> Booleans.Bool -> Booleans.Bool
(&&) = andb
(||) : Booleans.Bool -> Booleans.Bool -> Booleans.Bool
(||) = orb
andb_eq_orb : (b, c : Booleans.Bool) -> (b && c = b || c) -> b = c
there are obviously four cases and two hold for reflexivity.
andb_eq_orb True True _ = Refl
andb_eq_orb True False prf = ?rhs1
andb_eq_orb False True prf = ?rhs2
andb_eq_orb False False _ = Refl
Checking the holes reveals
Main.Booleans.rhs1
prf : True && False = True || False
---------------------------------
Main.Booleans.rhs1 : True = False
Main.Booleans.rhs2
prf : False && True = False || True
---------------------------------
Main.Booleans.rhs2 : False = True
I don't understand that while the assertions are obviuosly illogical that is what I need to prove for those two steps. I don't see any rewrite steps I could make. More but abstractly I dont understand the approach or pattern to solve this either logically or explicitly in the langauge (Idris).
I am able to get both of the approaches to work by implementing the Uninhabbited interface for the type signature as such:
Uninhabited (Booleans.True && Booleans.False = Booleans.True || Booleans.False) where
uninhabited Refl impossible

I'm not sure how did you define && and || and why they don't reduce for you, so let me show how this would work for stdlib Bool:
If you write the following:
andb_eq_orb : (b, c : Bool) -> (b && c = b || c) -> b = c
andb_eq_orb True True _ = Refl
andb_eq_orb True False prf = ?rhs1
andb_eq_orb False True prf = ?rhs2
andb_eq_orb False False _ = Refl
then
> :t rhs1
prf : False = True
--------------------------------------
rhs1 : True = False
Holes: Booleans.rhs2, Booleans.rhs1
> :t rhs2
prf : False = True
--------------------------------------
rhs2 : False = True
One way you could fill this would be simply by passing through these reduced proofs, swapping the sides where necessary:
andb_eq_orb : (b, c : Bool) -> (b && c = b || c) -> b = c
andb_eq_orb True True _ = Refl
andb_eq_orb True False prf = sym prf
andb_eq_orb False True prf = prf
andb_eq_orb False False _ = Refl
Another, proper way to do this would be to use the Uninhabited interface, which gives you a proof of Void given a contradictory premise. You can then use a void : Void -> a function (aka the principle of explosion), or a convenient synonym absurd = void . uninhabited:
andb_eq_orb : (b, c : Bool) -> (b && c = b || c) -> b = c
andb_eq_orb True True _ = Refl
andb_eq_orb True False prf = absurd prf
andb_eq_orb False True prf = absurd prf
andb_eq_orb False False _ = Refl

Related

Implement the functions using map and foldr, haskell

I have two functions. The first one gives true if all elements of the list are zero
allZero :: [Int] -> Bool
allZero [] = False
allZero [0] = True
allZero (x:xs)
| x == 0 && allZero xs = True
|otherwise = False
The second function gives true if at least one element of the list is zero
oneZero :: [Int] -> Bool
oneZero [] = False
oneZero (x:xs)
| x == 0 = True
| otherwise = oneZero xs
Maybe there is another way to solve this problems. For example with map or foldr?
Thank you
foldr function works so:
Suppose, you have list [1, 2, 3]. Let's write this list as (:) 1 ((:) 2 ((:) 3 [])), where each element has type a. Function foldr takes function f of a -> b -> b type and starting element z of b type, and just replace [] to z and : to f. So, foldr f z ((:) 1 ((:) 2 ((:) 3 []))) == f 1 (f 2 (f 3 z)).
So, you can define your functions so:
allZero = foldr (\x -> x == 0 &&) True
oneZero = foldr (\x -> x == 0 ||) False
foldr basically takes your guard as its folding function:
allZero = foldr (\x acc -> x == 0 && acc) True
acc (for accumulator) is the already-computed value of the recursive call. Being right-associative, the first non-zero value in the list short-circuits the evaluation of the fold function on the rest of the list.
(Note that allZero [] == True by convention. The "hypothesis" is that allZero xs is true, with evidence in the form of a non-zero element to falsify the hypothesis. No elements in the list, no evidence to contradict the hypothesis.)
I leave it as an exercise to adapt this to compute oneZero.

Im having an error with Haskell with cases that i cant find

So im trying to create this function AgregarMon that basically adds a "Monomio" to "Polinomio"
Monomio would end up being an element inside Polinomio which is a list. You are going to understand better in a little bit
type Monomio = (Int, Int)
type Polinomio = [Monomio]
agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon = \m p -> case m of{ (0,0) -> p;
x -> case p of{[] -> [x];
y:ys -> case (snd x == snd y) of { true -> case ((fst x + fst y)==0) of { true -> ys;
false -> (fst x + fst y , snd x):ys;}
false -> case snd x < snd y of{true -> y: agregarMon x ys;
false -> x:y:ys;}}}}
I've been looking at my code like an hour, and i cant find the problem. The error says:
Polinomios.hs:45:140: error:
Unexpected case expression in function application:
case ((fst x + fst y) == 0) of
true -> ys
false -> (fst x + fst y, snd x) : ys
You could write it with parentheses
Or perhaps you meant to enable BlockArguments?
|
45 | y:ys -> case (snd x == snd y) of { true -> case ((fst x + fst y)==0) of { true -> ys; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
Line 45 is the fourth line on the code from above. Im sorry if im missing info, please let me now.
Just in case, someone doesnt knows, fst and snd are on the Prelude. fst takes the first element from a "Monomio" snd the second one. fst = (a,b)->a snd (a,b) -> b
case (snd x == snd y) of { true ->
is wrong: true here is just a variable name, unrelated to the constructor True (with a capital T!). The snippet above is therefore equivalent to
case (snd x == snd y) of { x ->
Hence, the pattern matches any boolean value, True and False. For that reason the other branch false -> ... will never be considered.
I recommend you turn on warnings, since doing so makes GHC report the second branch as redundant code. The fact that the compiler considers a branch useless signals that something is very wrong with the code.
As a final note, in my experience code like
case something of
True -> a
False -> b
is not common, since we can write it as
if something
then a
else b
which is easier to read, in my view.
While you can, in a pinch, use curly brackets and semicolons, Haskell isn't a C-based language. It idiomatically uses indentation to indicate function scope.
Something like this would be more idiomatic:
agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon = \m p -> case m of
(0,0) -> p
x -> case p of
[] -> [x]
y:ys -> case (snd x == snd y) of
true -> case ((fst x + fst y)==0) of
true -> ys
false -> (fst x + fst y , snd x):ys
false -> case snd x < snd y of
true -> y: agregarMon x ys
false -> x:y:ys
This compiles (although with warnings, see below), but I don't know if it does what you want it to do. The OP code doesn't compile, so clearly something that does compile isn't equivalent.
All I did, however, was to remove all the curly brackets and semicolons, and instead 'fix' the indentation.
The code is still, in my opinion, too indented, but at least (with one exception) it stays left of 80 characters. Wide code could force people to scroll horizontally, which isn't going to make you many friends.
The above code loads in GHCi, but with warnings:
[1 of 1] Compiling Q58986486 ( 58986486.hs, interpreted )
58986486.hs:14:49: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: false -> ...
|
14 | false -> (fst x + fst y , snd x):ys
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
58986486.hs:15:39: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: false -> ...
|
15 | false -> case snd x < snd y of
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
58986486.hs:17:49: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: false -> ...
|
17 | false -> x:y:ys
| ^^^^^^^^^^^^^^^
Ok, one module loaded.
Thus, I'm not sure that it works as intended.
The version of Mark Seemann can be improved though.
Firstly, let's make m and p actual arguments of agregarMon:
agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon m p = case m of
(0,0) -> p
x -> case p of
[] -> [x]
y:ys -> case (snd x == snd y) of
true -> case ((fst x + fst y)==0) of
true -> ys
false -> (fst x + fst y , snd x):ys
false -> case snd x < snd y of
true -> y: agregarMon x ys
false -> x:y:ys
Now we can use pattern matching on agruments to simplify code:
agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon (0, 0) p = p
agregarMon x [] = [x]
agregarMon (f, s) (y:ys) = case (snd x == snd y) of
true -> case ((fst x + fst y)==0) of
true -> ys
false -> (fst x + fst y , snd x):ys
false -> case snd x < snd y of
true -> y: agregarMon x ys
false -> x:y:ys
It is not so idiomatic to pattern-match with case a result of condition check, better use if or guards:
agregarMon :: Monomio -> Polinomio -> Polinomio
agregarMon (0, 0) p = p
agregarMon x [] = [x]
agregarMon x#(coefx, powx) (y#(coefy, powy):ys)
| powx == powy = if coefx + coefy == 0
then ys
else (coefx + coefy, powx):ys
| powx < powy = y:agregarMon x ys
| otherwise = x:y:ys
Now we have some simple cases and a complex one, but even the complex one is not so hard to read and understand (I even made an assumption that you're working with polynomials, coefficients and powers).
You can run it there: https://repl.it/#Yuri12358/so-monomio-polinomio
Maybe this link will help you to improve your understanding of different ways to make branching in your code: http://learnyouahaskell.com/syntax-in-functions#pattern-matching

Lua xor function code

Does this code work as a xor function in Lua?
function xor (a,b)
if a ~= b then return true else return false end
end
i = false
j = false
if xor(not i, not j) then
print("one exclusive")
else
print("both or none")
end
Yes, your code works.
If a and b contain boolean values, then a XOR b is the same as not(a == b), which of course is the same as
a ~= b.

Can I define a "rec" function in another "rec" function in Ocaml?

I must make a function isFunction that takes a list of couples as an argument and return true if there is no repetition considering the first element in each couple and false if there is a repetition.
For example :isFunction [(1,3);(2,40);(3,40)] returns true but isFunction [(1,3);(2,40);(1,40)] returns false because 1 is repeated.
For now, my code is :
let rec exist e = function
|[] -> false
|(a,_)::l -> e=a || exist e l;;
let rec isFunction = function
|[]->true
|(a,_)::l -> not(exist a l) && isFunction l;;
which works perfectly! But the question is : is there another way to define isFunction without defining another auxiliary function?
You can declare exist as local to isFunction:
let rec isFunction l =
let rec exist e = function
|[] -> false
|(a,_)::l -> e=a || exist e l
in
match l with
|[]->true
|(a,_)::l -> not(exist a l) && isFunction l
You can use List.exists :
let isFunction = function
| [] -> true
| (a,_)::tl -> not (List.exists (fun (a',_) -> a'=a) tl) && isFunction l;;

Clojure: function arguments/signatures using macro or def

I have many functions of the same long signature (shortened here for simplicity):
(defn f
[x & {:keys [a b c d e f g h]
:or [a false b false c false d false e false f false g false h false]}]
a)
I was hoping to use a macro, function, or even a def to store this common signature beforehand:
(def args `[a b c d e f g h])
(defn args [] `[a b c d e f g h])
(defmacro args [] `[a b c d e f g h])
but all of them, when I plugged into
(defn f
[x & {:keys (args)
:or [a false b false c false d false e false f false g false h false]}]
a)
ended up with errors like
CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:1)
So my two questions are:
Is there any way to define and use such a common args?
If such an args can be defined, I would also like to reduce it in order to get the :or params: [a false b false c false d false e false f false g false h false]. How would this be done? (I'm asking in case a working definition of args might be weird enough that this is no longer straightforward.)
The problem is that the stuff inside the argument vector in a defn doesn't get evaluated. However, you can define your own version of defn, like so:
user=> (defmacro mydefn [name & body] `(defn ~name ~'[a b c] ~#body))
#'user/mydefn
user=> (mydefn f (+ a b))
#'user/f
user=> (f 1 2 4)
3
Note the need for ~' for the arguments. Otherwise syntax-quote (`) would qualify the symbols into user.a etc.