SML: Error: match redundant and Warning:match nonexhaustive - sml

I am getting both of these issues for this function:
fun funion([(x:int list,y:bool list)]) =
let
fun join(nil,final) = final |
join(x::xs,final) = join(xs,union(x,final)) |
join(_,final) = final
in
join([(x,y)],(nil,nil))
end;
Here is the error:
sets.sml:30.6-32.27 Error: match redundant
(nil,final) => ...
(x :: xs,final) => ...
--> (_,final) => ...
sets.sml:28.5-35.4 Warning: match nonexhaustive
(x,y) :: nil => ...
Does anyone know what might be going on here? I also tried join(_) but that did not work either. Not sure what the problem is here.
uncaught exception Error
Edit:
Here is the definition of union:
fun union((w:int list,x:bool list),(y:int list,z:bool list)) =
let
fun join((nil,nil),final) = final |
join((w::ws,x::xs),(intfinal,boolfinal)) = if x andalso elementOf(w,(intfinal,boolfinal))=false then join((ws,xs),(w::intfinal,true::boolfinal)) else join((ws,xs),(intfinal,boolfinal)) |
join(_,final) = final
in
join((w,x),join((y,z),(nil:int list,nil:bool list)))
end;

I gather that funion is supposed to have type
(int list * bool list) list -> (int list * bool list)
But -- you only provide a definition for lists of length 1, which gives a non-exhaustive list warning.
For the inner function join you provide a definition first for patterns of the form (nil, final) and then for patterns of the form (x::xs,final). Since the first component is either empty or matches the pattern x::xs and any list whatsoever matches final, any further pattern is redundant. Perhaps you want the three patterns
1) (nil,ys)
2) (xs,nil)
3) (xs,ys)
A final remark -- if you are happy with union -- why not just use it with foldl or foldl if you have a list of (int list * bool list) and what the union of them all?

"Error: match redundant" means that a pattern doesn't match anything that previously-tested matches wouldn't also match. In your case, you have the match-pattern (nil, final) (which matches any pair whose first element is the empty list) and the match-pattern (x::xs, final) (which matches any pair whose first element is a non-empty list), which together cover all cases . . . and then you have the match-pattern (_, final), which doesn't match anything new. Technically this doesn't need to be an error — the compiler could just issue a warning and discard this match — but it's such a serious warning that SML/NJ treats it as an error.
"Warning: match nonexhaustive" means that your match-patterns don't cover all cases. In your case, the match-pattern ([(x:int list,y:bool list)]) can only match a single-element list. (You probably just meant to write (x:int list, y:bool list), without the [...] notation to match a list of hardcoded length.)

Related

How to partially match a pattern in OCaml

I have a list lst of objects of type value where
type value = A of int | B of bool | C of string
In doing some matching on the the list, I tried to write
match lst with
| A x :: val :: tl -> ...
and got an exception saying that in the variable val a pattern was expected. I am assuming this is because in the head of the list I matched on a value variant, but for val I wanted to capture all possible next entries in the list. I can think of some ways around them, like writing several cases for the several variants of val. But since I want to do the same basic thing no matter what val is, that seems like a very inelegant solution. Is there a better solution?
Elaborating an answer based on glennsl's comment, I assume this snippet entered into the top level is reproducing the syntax error you're hitting:
since val is a reserved keyword, it is not legal to use it in pattern matches. The error is saying that the underlined token val is triggering a syntax error since it is expecting something that could be part of a pattern.
The following should compile without any problems (using some random values for example):
type value = A of int | B of bool | C of string
match [A 1; B true; C "foo"] with
| A x :: v :: tl -> Some (x, v)
| _ -> None
And this is simply due to the replacement of the keyword val with the variable v in the pattern.

Type mismatch OCaml?

I have a problem, OCaml thinks the a and s parameters of my function are unit lists, but they have to be 'a list and string respectively. The function has to output the list elements separated by the given separator.
The result has to be a string, with the below input: "This-is-label"
P.S. I know about match, but I can`t use it
let rec function1 a s =
if a = [] then failwith "Empty list" else
if List.tl a = [] then List.hd a else
if List.tl a != [] then List.hd a; s; function1 List.tl a s
;;
function1 ["This"; "is"; "label"] "-";;
It seems you expect this expression to be a string:
List.hd a; s; function1 List.tl a s
However, the meaning of the ; operator is to evaluate the expression at the left and then ignore its value. (It is also considered bad form if the type isn't unit.) Then evaluate the expression at the right, which is the value of the expression.
So this expression says to evaluate List.hd a, then forget the value. Then evaluate s, then forget the value. Then evaluate the recursive call.
So the first problem is to assemble these things into a string.
The ^ operator concatenates two strings. So something like this is closer to what you want:
List.hd a ^ s ^ function1 (List.tl a) s
Note that you need to parenthesize the call to List.tl. Otherwise it looks like two separate parameters to function1.
The problem in your code are missing () around List.tl a in the recursive call. Also ^ must be used to concatenate the strings instead of ;. The code is still very un-ocaml like.
There really is no good way to do this without pattern matching. If this is a homework assignment where you aren't allowed to use pattern matching then please give your instructor a big kick in the behind.
The order of arguments also would be better the other way around, have the separator as first argument. That way you can bind the function to a separator and reuse it many times.
Two alternative implementations:
let rec join s = function
| [] -> "" (* or failwith "Empty list" if you insist *)
| [x] -> x
| x::xs -> x ^ s ^ join s xs
let join s a =
let (res, _) =
List.fold_left
(fun (acc, sep) x -> (x ^ sep ^ acc, s))
("", "")
a
in
res

Eliminate consecutive duplicates of list elements ocaml

I am working on "99 Ocaml Problems" and in the solution, I see this pattern matching:
let rec compress (mylist : 'a list) : 'a list = match mylist with
|a::(b::_ as t) -> if a = b then compress t else a::compress t
|smaller -> smaller
I understand that for the first matching case, if element a is the same as element b, then I move on to the list t. If not, I will append element a to the list of compressing t.
For the second matching case, I am not sure what is the type of "smaller".
When I try to put a square bracket around it since I am thinking the author wants to match second case with one element list, but I have a non-exhaustive pattern.
Can you explain to me what the "smaller" is in this case?
The variable smaller is an 'a list. It matches anything that doesn't match the earlier branch, i.e., a list with one element or the empty list.
Another way to write the compress function without smaller:
let rec compress (mylist : 'a list) : 'a list = match mylist with
| a::(b::_ as t) -> if a = b then compress t else a::compress t
| _ -> mylist;;
Which says the same as the answer of user tbrk : if mylist does not match the first expression, then compress mylist returns mylist.

How turn list of pair in list of int, where result int is sum of pair

I try to define function with the following protocol:
[(1,2), (6,5), (9,10)] -> [3, 11, 19]
Here is what I have now:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else (#1 hd(l)) + (#2 hd(l))::sum_pairs(tl(l))
According to type checker I have some type mismatch, but I can't figure out where exactly I'm wrong.
This code runs in PolyML 5.2:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else ((#1 (hd l)) + (#2 (hd l))) :: sum_pairs(tl l)
(* ------------^-------------^ *)
The difference from yours is subtle, but significant: (#1 hd(l)) is different from (#1 (hd l)); the former doesn't do what you think - it attempts to extract the first tuple field of hd, which is a function!
While we're at it, why don't we attempt to rewrite the function to make it a bit more idiomatic? For starters, we can eliminate the if expression and the clunky tuple extraction by matching on the argument in the function head, like so:
fun sum_pairs [] = []
| sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest)
We've split the function into two clauses, the first one matching the empty list (the recursive base case), and the second one matching a nonempty list. As you can see, this significantly simplified the function and, in my opinion, made it considerably easier to read.
As it turns out, applying a function to the elements of a list to generate a new list is an incredibly common pattern. The basis library provides a builtin function called map to aid us in this task:
fun sum_pairs l = map (fn (a, b) => a + b) l
Here I'm using an anonymous function to add the pairs together. But we can do even better! By exploiting currying we can simply define the function as:
val sum_pairs = map (fn (a, b) => a + b)
The function map is curried so that applying it to a function returns a new function that accepts a list - in this case, a list of integer pairs.
But wait a minute! It looks like this anonymous function is just applying the addition operator to its arguments! Indeed it is. Let's get rid of that too:
val sum_pairs = map op+
Here, op+ denotes a builtin function that applies the addition operator, much like our function literal (above) did.
Edit: Answers to the follow-up questions:
What about arguments types. It looks like you've completely eliminate argument list in the function definition (header). Is it true or I've missed something?
Usually the compiler is able to infer the types from context. For instance, given the following function:
fun add (a, b) = a + b
The compiler can easily infer the type int * int -> int, as the arguments are involved in an addition (if you want real, you have to say so).
Could you explain what is happening here sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest). Sorry for may be dummy question, but I just want to fully understand it. Especially what = means in this context and what order of evaluation of this expression?
Here we're defining a function in two clauses. The first clause, sum_pairs [] = [], matches an empty list and returns an empty list. The second one, sum_pairs ((a, b)::rest) = ..., matches a list beginning with a pair. When you're new to functional programming, this might look like magic. But to illustrate what's going on, we could rewrite the clausal definition using case, as follows:
fun sum_pairs l =
case l of
[] => []
| ((a, b)::rest) => (a + b)::sum_pairs(rest)
The clauses will be tried in order, until one matches. If no clause matches, a Match expression is raised. For example, if you omitted the first clause, the function would always fail because l will eventually be the empty list (either it's empty from the beginning, or we've recursed all the way to the end).
As for the equals sign, it means the same thing as in any other function definition. It separates the arguments of the function from the function body. As for evaluation order, the most important observation is that sum_pairs(rest) must happen before the cons (::), so the function is not tail recursive.

What does (x:_) and [x:_] mean?

head' :: [a] -> a
head' [] = error "No head for empty lists!"
head' (x:_) = x
head' :: [a] -> a
head' xs = case xs of [] -> error "No head for empty lists!"
(x:_) -> x
I am asking for a fairly easy question which I don't understand.
In the code above, I see that it takes a list for an input.
But on the third line, it says (x:_) which confuses me.
Can anyone explain to me why they wrote (x:_) instead of [x:_]?
And plus, I don't understand what (x:_) means.
Thank you.
: is a constructor for lists, which takes the head of the new list as its left argument and the tail as its right argument. If you use it as a pattern like here that means that the head of the list you match is given to the left pattern and the tail to the right.
So in this case the head of the list is stored in the variable x and the tail is not used (_ means that you don't care about the value).
And yes, you can also use [] to pattern match against lists, but only lists of fixed size. For example the pattern [x] matches a list with exactly one element, which is then stored in the variable x. Likewise [x,y] would match a list with two elements.
Your proposed pattern [x:y] would thus match a list with one element, which matches the pattern x:y. In other words, it would match a list of lists which contains exactly one list.
This is a concept called pattern matching. : is an infix constructor, just like + is an infix function. In Haskell you pattern match with constructors.
(1 : 2 : 3 : [])
Is the same as [1, 2, 3], the square bracket notation is just syntactic sugar for creating lists.
Your pattern (x : _) means that you want to bind the first element of the list to x and that you do not care about the rest of the list _.