SML List Deletion - sml

I am trying to write a function to delete a list from another list.
''a list -> ''a list -> ''a list
Here's what I have so far:
fun delete _ [] = [] |
delete (h1::t1) (h2::t2) =
if h1=h2
then t2
else h2::delete (h1::t1) t2;
I am using MoscowML and it gives me a Warning: pattern matching is not exhaustive error.
A test of the above function:
- delete [4,5] [1,2,3,4,5,6,7,8];
> val it = [1,2,3,5,6,7,8] : int list
The desired output is:
> val it = [1,2,3,6,7,8] : int list

There are two issues here:
1- Why is the interpreter raising the Warning: pattern matching is not exhaustive error
2- What can be done to make the code working.
Concerning the first point, the reason for the warning is because that you are not checking every possibility that may occur. The function delete as it currently stands checks only for two possibilities:
-1 The second list being the empty list (covered by the pattern: _ [] = )
-2 Both lists not being empty (covered by the second pattern: (h1::t1) (h2::t2) =)
However, there is a third possibility, namely the first list being the empty list. Therefore, the following input would result in an error: delete [] [1,2,3,4,5,6]
Concerning the second point, if the exact requirement is to delete from the second list the elements of the first list in succession and only once, then your solution is very close. The else branch is fine, only the then branch needs more attention.
By correcting the then branch I get following results:
delete [4,5] [1,2,3,4,5,6,7,8] = [1,2,3,6,7,8];
delete [5,4] [1,2,3,4,5,6,7,8] = [1,2,3,4,6,7,8];
delete [4,4,5] [1,2,3,4,5,6,7,8] = [1,2,3,5,6,7,8];
delete [4,5,6] [1,2,3,4,5,6,7,8] = [1,2,3,7,8];
delete [4,6,5] [1,2,3,4,5,6,7,8] = [1,2,3,5,7,8];
delete [4,6,5] [1,2,3,4,6,7,8,5] = [1,2,3,7,8];
If however you want to delete all the elements of the first list occurring in the second list regardless of their order, then you will need to rethink your approach.
for instance, if you want the following result:
delete [4,6,5] [1,2,3,4,4,5,5,5,4,4,6,6,5,5,6,6,6,6,6,7,8,5] = [1,2,3,7,8];
then you need to do it in two steps:
First write a function del that given one element will delete all its occurrences in a list: fun del e l = ...
The implementation thereof is practically identical to the one you provided for delete, except you will need to change the then branch slightly.
After you have del, now you can implement the function delete that given a list, it will delete all the occurrences of that list in the second list. Here you will use the previously defined function del.

Related

Pattern matching on rest of list

I'm trying to pattern match on a list of pairs, where I'm trying to return a list from the list of pair, however I'm having trouble figuring out where to make the recursive call. Without the recursive call I have this:
let countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]
;;
But naturally this only applies to the first pair in the list and simply returns ["countryA"; "countryB"] without the rest of the list.
With the recursive call this simply only returns an empty list:
let rec countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]::countriesInChart tt
;;
How would I make the recursive call such that all the pairs in the list would return as a list?
You have this:
[x;y] :: countriesInChart tt
This says to add a new list of two elements onto the front of a list of lists.
I don't think you want a list of lists, you just want a list. So you shouldn't be making a list of two elements.
If x and y are the same type (as I suspect they are), what you probably want is this:
x :: y :: countriesInChart tt
This says to add both x and y individually to the front of the recursively generated list.
You can also write this, which is completely equivalent:
[x; y] # countriesInChart tt
However, this constructs a list of two elements only to throw it away. So it's a tiny bit of extra work for no benefit.

Prolog: assign the tail of a list to a variable?

I have some prolog code below, which takes a list of integers, and returns me the Max element of said list. My issue is that I'm not quite sure how theList = [H|_] portion of the code works.
I understand that H gets assigned the head value of the list, but the variable List below is what? How does prologue know to take the tail and assign it to List when given the following snippet of code List = [H|_]
To me List could either be H or it could be _ (the tail)... but logically it has to be _ (the tail) or the function below would not work.
max(List,Max) :-
List = [H|_],
accMax(List,H,Max).
Example of code : http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse21

OCaml count consecutive elements in a list

I'm writing OCaml code that reads in a list and removes any char 'i's that appear at the beginning of the list. For instance, the list removeI['i';'i';'a';'c';'i'] should return -: int * char list = ['a';'c';'i'], because there are 2 'i's at the beginning of the list. I believe I know how to implement this properly; however, I want to return a tuple that includes the number of removed 'i's as well as the new list with the 'i's removed. I know that may sound confusing, but an example would be removeI['i';'i';'a';'c';'i'] -: int * char list = (2,['a';'c';'i']) There are 2 'i's removed and the new list with the removed 'i's.
So far, I have the following function:
let rec removeI list = match list with
| [] -> []
| x::[] -> x::[]
| x::y::t1 -> if x='i' then removeI (y::t1)
else list;;
This returns the list with the first 'i's removed, but I keep getting errors when I try to include the number of removed 'i's as part of a tuple. Could anyone push me in the right direction? Thanks!
Your recursive call will return the same type as the function overall. So if you change the function to reuturn (count, list), then the recursive call will return that also.
Generally you want to gather up the returned values and calculate a new value from them.
Right now you have just this:
removeI (y :: t1)
But you need something more like this:
let (count, list) = removeI (y :: t1) in
(* Newly calculated count and list *)
Note that your base cases also have to return a count and a list.
As a side comment, I don't actually understand your second base case. You don't want to remove an 'i' if it's the only thing in the list? That doesn't seem particularly consistent.

SML - Merge Two Lists

I have a SML problem. I need to write a SML function to merge two lists and returns a list of distinct elements.
For example:
- merge [1,2,3,4,5] [4,5,6,7,8];
val it = [1,2,3,4,5,6,7,8] : int list
-merge ["a", "a"] nil;
val it = ["a"] : string list
I only can create a function to merge two lists but cannot remove distinct elements.
- fun merge list1 list2 = list1#list2;
val merge = fn : 'a list -> 'a list -> 'a list
- merge [1,2,3] [3,4,5];
val it = [1,2,3,3,4,5] : int list
How to write a function to merge two lists and remove distinct elements?
Thanks
You'll need two functions---a function that deletes elements, and another function that deletes duplicate elements. The delete function would take argument (item,lst), and delete all the elements in lst that are equal to item.
delete(item,lst) = ...
Next step would be to strip duplicate elements. This function takes your list as an argument. You'll have to use delete function delete items recursively, except for the unique element.
if null hd(lst) then []
else hd(lst)::strip_duplicates(delete(hd(lst),tl(lst)))
I believe you have not told us the entire truth about your problem. It seems that if the lists you wish to merge are sorted, you can compare the first element in each list and put the smallest one in the resulting list. This way the merged list will also be sorted.
The trick here is to realize that while you compare them, if they are equal, you don't actually need to include both in the result, while if they are not equal, you need to include them in the right order.

nested lists in ocaml

I am new to Ocaml and have defined nested lists as follows:
type 'a node = Empty | One of 'a | Many of 'a node list
Now I want to define a wrapping function that wraps square brackets around the first order members of a nested list. For ex. wrap( Many [ one a; Many[ c; d]; one b; one e;] ) returns Many [Many[one a; Empty]; Many[Many[c;d]; Empty]; Many[b; Empty]; Many[e; Empty]].
Here's my code for the same:
let rec wrap list = function
Empty -> []
| Many[x; y] -> Many [ Many[x; Empty]; wrap y;];;
But I am getting an error in the last expression : This expression has the type 'a node but an expression was expected of the type 'b list. Please help.
Your two matches are not returning values of the same type. The first statement returns a b' list; the second statement returns an 'a node. To get past the type checker, you'll need to change the first statement to read as: Empty -> Empty.
A second issue (which you will run into next) is that your recursive call is not being fed a value of the correct type. wrap : 'a node -> 'a node, but y : 'a node list. One way to address this would be to replace the expression with wrap (Many y).
There will also be in issue in that your current function assumes the Many list only has two elements. I think what you want to do is Many (x::y). This matches x as the head of the list and y as the tail. However, you will then need a case to handle Many ([]) so as to avoid infinite recursion.
Finally, the overall form of your function strikes me as a bit unusual. I would replace function Empty -> ... with match list with | Empty -> ....