I am using pattern matching on argument passed to a function. The method works fine for "first level" matching so to say but any attempt to go deeper gives the error "stdIn:282.5-291.77 Error: match redundant"
example
fun nnf T = T
| nnf F = F
| nnf (LETTER(x)) = (LETTER(x))
| nnf (NEG(x)) = (NEG(nnf x))
| nnf (AND(x,y)) = (AND(nnf x, nnf y))
| nnf (OR(x,y)) = (OR(nnf x, nnf y))
| nnf (IMP(x,y)) = (OR(NEG(nnf x),(nnf y)))
| nnf (NEG(NEG(LETTER(x)))) = (LETTER(x))
| nnf (NEG(AND(LETTER(x),LETTER(y)))) = (OR(NEG(LETTER(x)),NEG(LETTER(y))))
| nnf (NEG(OR(LETTER(x),LETTER(y)))) = (AND(NEG(LETTER(x)),NEG(LETTER(y))));
val nnf = fn : prop -> prop
the error i get is
stdIn:282.5-291.77 Error: match redundant
T => ...
F => ...
LETTER x => ...
NEG x => ...
AND (x,y) => ...
OR (x,y) => ...
IMP (x,y) => ...
--> NEG (NEG (LETTER x)) => ...
--> NEG (AND (LETTER x,LETTER y)) => ...
--> NEG (OR (LETTER x,LETTER y)) => ...
so SML is saying that the last 3 clauses in the function definition are the same since they all begin with "(NEG(..." even though what follows is different.
how do i overcome this ?
The case NEG(x) already covers any possible case involving outermost NEG, so the others are never reached. Depending on what you actually want to achieve, either remove that case, or move it after the more specific ones (cases are tried in order).
Related
I'm confused about the all introduction meta rule in Isabelle. The papers say it should be:
From P deduce ⋀ x. P whenever x is not a free variables in the asumptions.
This is confusing to me. I understand better wikipedia's one:
From (P y) deduce ⋀ x. P x whenever y is not free in the (implicit) assumptions and x is not free in P.
How is the meta-forall rule encoded in Isabelle? Here is the source code:
(*Forall introduction. The Free or Var x must not be free in the hypotheses.
[x]
:
A
------
⋀x. A
*)
fun forall_intr
(ct as Cterm {maxidx = maxidx1, t = x, T, sorts, ...})
(th as Thm (der, {maxidx = maxidx2, shyps, hyps, tpairs, prop, ...})) =
let
fun result a =
Thm (deriv_rule1 (Proofterm.forall_intr_proof x a) der,
{cert = join_certificate1 (ct, th),
tags = [],
maxidx = Int.max (maxidx1, maxidx2),
shyps = Sorts.union sorts shyps,
hyps = hyps,
tpairs = tpairs,
prop = Logic.all_const T $ Abs (a, T, abstract_over (x, prop))});
fun check_occs a x ts =
if exists (fn t => Logic.occs (x, t)) ts then
raise THM ("forall_intr: variable " ^ quote a ^ " free in assumptions", 0, [th])
else ();
in
(case x of
Free (a, _) => (check_occs a x hyps; check_occs a x (terms_of_tpairs tpairs); result a)
| Var ((a, _), _) => (check_occs a x (terms_of_tpairs tpairs); result a)
| _ => raise THM ("forall_intr: not a variable", 0, [th]))
end;
Suppose I am a mathematician with only some notions of programming. How would you convince me the piece of code below implements the meta-forall rule in a sensible manner?.
I am new to SML.I got this sorting algo to implement where in each iteration,I have to pick minimum element from the list, remove it and create sorted list.
I did below coding to solve the problem.
I wrote 2 helper functions to pickup minimum element from the list and remove one element from the list.
fun minList(x::xs) =List.foldl (fn (x,y)=> if x<y then x else y) x (x::xs);
fun remElem(x, l) =
case l of
[] => []
| (x1::x2::xs) => if x1=x then (x2::xs) else (x1::xs)
;
Above two programs ran successfully.
Below is my sorting code.
fun simpSort(xs)=
let fun aux(xs,acc)=
case xs of
[] =>acc
| [x] => [x]
| (x::xs) => let val m = minList(xs)
in
aux(remElem(m,xs),acc#[m])
end
in aux(xs,[])
end;
This sorting program is giving error.
simpSort([3,1]);
uncaught exception Match [nonexhaustive match failure]
raised at: stdIn:433.59
Please advise.
Since you've solved your problem, here are some hints for improving a working version of your code:
Find the minimum of a list in a way that supports empty lists:
fun minimum [] = NONE
| minimum (x::xs) = SOME (foldl Int.min x xs)
Simplify pattern matching in the function that removes the first occurrence of an element from a list:
fun remove (_, []) = []
| remove (y, x::xs) =
if x = y
then xs
else x :: remove (y, xs)
Use those in combination to write simpSort:
fun simpSort xs =
case minimum xs of
NONE => []
| SOME x => x :: simpSort (remove (x, xs))
I shouldn't have to say that this sorting algorithm is terribly inefficient. :-P
Ok, so I'm trying to change this function into Tail Recursive. The Definition I have of Tail Recursive is to use a "Local Helper Function" to accumulate my answer and return it without calling the primary function recursively.
these functions work properly.
fun same_string(s1 : string, s2 : string) =
s1 = s2
fun all_except_option (name, []) = NONE
| all_except_option (name, x::xs)=
case same_string (x , name) of
true => SOME xs
| false => case all_except_option(name,xs) of
NONE => NONE
| SOME z => SOME(x::z)
fun get_substitutions1 ([],name2) = [] (*get_substitutions2 is same but tail recursive *)
| get_substitutions1 (x::xs,name2) =
case all_except_option (name2,x) of
NONE => get_substitutions1 (xs,name2)
| SOME z => z # get_substitutions1(xs,name2)
So here are my attempts at tail recursion which do not work and I think I am missing something fairly basic that I am overlooking due to my lack of experience in SML.
fun get_substitutions2 (lst,name3) =
let fun aux (xs,acc) =
case all_except_option(name3,x::xs) of
NONE => aux(xs, acc)
| SOME z => aux(xs, z::acc)
in
aux(lst,[])
end
and
fun get_substitutions2 (lst,name3) =
let fun aux (xs,acc) =
case all_except_option(name3,x::xs) of
NONE => aux(xs, acc)
| SOME z => aux(xs, z#acc)
in
aux(lst,[""])
end
Both "get_substitutions" functions are supposed to do the same thing.
compare String1 to string list list, return single list made up of all lists containing String1 minus String1.
My attempts at using Tail Recursion have resulted in the following error.
Error: unbound variable or constructor: x
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:296.17-
Here are a few examples of calling get_substitutions2:
get_substitutions2 ([["foo"],["there"]], "foo"); (* = [] *)
get_substitutions2 ([["fred","fredrick","freddie","F","freddy"],["Will","William","Willy","Bill"]],"Bill"); (* = ["Will","William","Willy"] *)
get_substitutions2 ([["a","b"],["a","c"],["x","y"]], "a"); (* = ["c","b"] *)
You need to use the same patterns you had for get_substitutions1 in your aux function definition:
fun get_substitutions2 (lst,name3) =
let fun aux ([],acc) = acc (* BASE CASE *)
| aux (x::xs,acc) = (* BINDING x IN PATTERN *)
case all_except_option(name3,x) of
NONE => aux(xs, acc)
| SOME z => aux(xs, z#acc)
in
aux(lst,[])
end
Define a function which computes the sum of all the integers in a
given list of lists of integers. No 'if-then-else' or any auxiliary
function.
I'm new to to functional programming and am having trouble with the correct syntax with SML. To begin the problem I tried to create a function using pattern matching that just adds the first two elements of the list. After I got this working, I was going to use recursion to add the rest of the elements. Though, I can't even seem to get this simple function to compile.
fun listAdd [_,[]] = 0
| listAnd [[],_] = 0
| listAnd [[x::xs],[y::ys]] = x + y;
fun listAdd [] = 0
| listAdd ([]::L) = listAdd L
| listAdd ((x::xs)::L) = x + listAdd (xs::L)
should do what it looks like you want.
Also, it looks like part of the problem with your function is that you give the function different names (listAdd and listAnd) in different clauses.
For the sake of simplicity, I'd say you probably want this :
fun listAdd : (int * int) list -> int list
Now, I would simply define this as an abstraction of the unzip function :
fun listAdd ls :
case ls of
[] => 0
| (x,y) :: ls' => (x + y) + (listAdd ls')
I think there is no point in taking two separate lists. Simply take a list that has a product of ints. If you have to build this, you can call the zip function :
fun zip xs ys :
case xs, ys of
[], [] => []
| xs, _ => []
| _, ys => []
| x::xs', y::ys' => (x,y) :: (zip xs' ys')
In general, if you really wanted, you can write a far more abstract function that is of the general type :
fun absProdList : ((`a * `b) -> `c) -> (`a * `b) list -> `c list
This function is simply :
fun absProdList f ls =
case l of
[] => []
| (x,y) :: ls' => (f (x,y)) :: (absProdList f ls')
This function is a supertype of the addList function you mentioned. Simply define an anonymous function to recreate your addList as :
fun addList' ls =
absProdList (fn (x,y) => x + y) ls
As you can see, defining the generic type-functions makes specific calls to functions that are type-substitutions to the general one far easier and much more elegant with the appropriate combination of : Currying, Higher-Order Functions and Anonymous Functions.
You probably don't want an int list list as input, but simply an int list * int list (pair of int lists). Besides this, your function seems to returns numbers rather than a list of numbers. For this you would use recursion.
fun listAdd (x::xs, y::ys) = (x + y) :: listAdd (xs, ys)
| listAdd ([], _) = []
| listAdd (_, []) = [] (* The last two cases can be merged *)
You probably want to read a book on functional programming fron the first page and on. Pick for example Notes on Programming in SML/NJ by Riccardo Pucella if you want a free one.
I'm coding in SML for an assignment and I've done a few practice problems and I feel like I'm missing something- I feel like I'm using too many case statements. Here's what I'm doing and the problem statements for what I'm having trouble with.:
Write a function all_except_option, which takes a string and a string list. Return NONE if the string is not in the list, else return SOME lst where lst is like the argument list except the string is not in it.
fun all_except_option(str : string, lst : string list) =
case lst of
[] => NONE
| x::xs => case same_string(x, str) of
true => SOME xs
| false => case all_except_option(str, xs) of
NONE => NONE
| SOME y=> SOME (x::y)
Write a function get_substitutions1, which takes a string list list (a list of list of strings, the substitutions) and a string s and returns a string list. The result has all the strings that are in some list in substitutions that also has s, but s itself should not be in the result.
fun get_substitutions1(lst : string list list, s : string) =
case lst of
[] => []
| x::xs => case all_except_option(s, x) of
NONE => get_substitutions1(xs, s)
| SOME y => y # get_substitutions1(xs, s)
-
same_string is a provided function,
fun same_string(s1 : string, s2 : string) = s1 = s2
First of all I would start using pattern matching in the function definition
instead of having a "top-level" case statement. Its basically boils down to the
same thing after de-sugaring. Also I would get rid of the explicit type annotations, unless strictly needed:
fun all_except_option (str, []) = NONE
| all_except_option (str, x :: xs) =
case same_string(x, str) of
true => SOME xs
| false => case all_except_option(str, xs) of
NONE => NONE
| SOME y => SOME (x::y)
fun get_substitutions1 ([], s) = []
| get_substitutions1 (x :: xs, s) =
case all_except_option(s, x) of
NONE => get_substitutions1(xs, s)
| SOME y => y # get_substitutions1(xs, s)
If speed is not of importance, then you could merge the two cases in the first function:
fun all_except_option (str, []) = NONE
| all_except_option (str, x :: xs) =
case (same_string(x, str), all_except_option(str, xs)) of
(true, _) => SOME xs
| (false, NONE) => NONE
| (false, SOME y) => SOME (x::y)
But since you are using append (#), in the second function, and since it is not
tail recursive, I don't believe that it your major concern. Keep in mind that
append is potential "evil" and you should almost always use concatenation (and
then reverse your result when returning it) and tail recursion when possible (it
always is).
If you really like the explicit type annotations, then you could do it like this:
val rec all_except_option : string * string list -> string list option =
fn (str, []) => NONE
| (str, x :: xs) =>
case (same_string(x, str), all_except_option(str, xs)) of
(true, _) => SOME xs
| (false, NONE) => NONE
| (false, SOME y) => SOME (x::y)
val rec get_substitutions1 : string list list * string -> string list =
fn ([], s) => []
| (x :: xs, s) =>
case all_except_option(s, x) of
NONE => get_substitutions1(xs, s)
| SOME y => y # get_substitutions1(xs, s)
But that is just my preferred way, if I really have to add type annotations.
By the way, why on earth do you have the same_string function? You can just do the comparison directly instead. Using an auxilary function is just wierd, unless you plan to exchange it with some special logic at some point. However your function names doesn't sugest that.
In addition to what Jesper.Reenberg mentioned, I just wanted to mention that a match on a bool for true and false can be replaced with an if-then-else. However, some people consider if-then-else uglier than a case statement
fun same_string( s1: string, s2: string ) = if String.compare( s1, s2 ) = EQUAL then true else false
fun contains( [], s: string ) = false
| contains( h::t, s: string ) = if same_string( s, h ) then true else contains( t, s )
fun all_except_option_successfully( s: string, [] ) = []
| all_except_option_successfully( s: string, h::t ) = if same_string( s, h ) then t else ( h :: all_except_option_successfully( s, t ) )
fun all_except_option( s: string, [] ) = NONE
| all_except_option( s: string, h::t ) = if same_string( s, h ) then SOME t else if contains( t, s ) then SOME ( h :: all_except_option_successfully( s, t ) ) else NONE