Given a list create a list of tuples SML - functional-programming

Hello I am new to Sml/nj, and I am trying to modify an input to give it to a function. I'm stuck at modifying the input.
Specifically, I read the input and store it in a list. I want to make a function that given an even length list, it will make a new list, but with 2-element tuples.
For example, if my input is the list [2, 7, 4, 6, 5, 8] I want to create this list [(2, 7), (4, 6), (5, 8)]
I tried this but unfortunately it doesn't work:
fun maketuples [] = []
| maketuples x::xs = (x, hd xs) # makektuples (tl xs)

There's a couple things here:
If you're pattern matching on a constructor as a function argument, you need to put parentheses around it for it to be parsed the way you'd like, i.e., x::xs -> (x::xs)
You have a typo in the second clause (makektuples; extra k)
You're using append (#) on a int * int and a (int * int) list. The domain of this function is in fact, 'a list * 'a list, i.e., both of its arguments must be lists of the same type.
We could revise this like so:
fun maketuples [] = []
| maketuples (x::xs) = [(x, hd xs)] # maketuples (tl xs)
But singleton append isn't really something you should do. Why? It's cleaner to just use cons:
fun maketuples [] = []
| maketuples (x::xs) = (x, hd xs) :: maketuples (tl xs)
We can clean this up some more by removing the calls to hd and tl by just destructing further in the function arguments
fun maketuples [] = []
| maketuples (x::y::xs) = (x, y) :: maketuples xs
and you could perhaps handle an error better (one possibility being with exceptions):
fun maketuples [] = []
| maketuples (x::y::xs) = (x, y) :: maketuples xs
| maketuples _ = raise Fail "Not an even length list"

Related

OCaml function apparently works but does not return the expected result

Who can help? I am a beginner in OCaml, I am trying to perform an action of unpacking sets. Having a set [(1, 4); (2, 5); (3, 6)] I want to get the exit [(1,2,3), (4,5,6)]. I am using a script that I tested with Haskell and it worked, but in OCaml, it does not show the result. Where am I going wrong? I could not figure out where my mistake is. Thx.
let fst num1 num2 =
match num1, num2 with
| (x, y) -> x;;
let snd num1 num2 =
match num1, num2 with
| (x, y) -> y;;
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (xs, ys)
| (xs, ys, z :: zs) -> dcp_base (xs # [fst z]) (ys # [snd z]) zs;;
let descompact list =
match list with
| [] -> ([], [])
| xs -> dcp_base [] [] xs;;
The problem is your redefinition of fst and snd. They're not needed, as they're already defined in the standard library and in scope with exactly those names. But they're also wrong. Your implementation takes two arguments and selects either the first or second in a roundabout way by creating an intermediary tuple, instead of a singe tuple argument directly. Therefore, when you apply it to a single tuple argument it will return a partially applied function expecting the second argument.
You can fix the problem just by removing the definitions of fst and snd from your code, but if you absolutely want to reimplement it, it ought to look something more like this:
let fst (x, _) = x;;
let snd (_, y) = y;;
Your fst and snd functions are actually strange since you take two arguments to return the first one or the second one. I guess you wanted to get the first or second element of a pair so you should write (from most detailed to least detailed)
(* too much details *)
let fst num = match num with (x, y) -> x
let snd num = match num with (x, y) -> y
(* let's use the wildcards *)
let fst num = match num with (x, _) -> x
let snd num = match num with (_, y) -> y
(* do we really need num? *)
let fst = function (x, _) -> x
let snd = function (_, y) -> y
(* do we really need to match on a single pattern? *)
let fst (x, _) = x
let snd (_, y) = y
And it should work.
As a side note, fst and snd already exist in the standard library but it's never wrong to try implementing them yourself
Second side note, appending at the end of a list is usually not advised (not tail recursive, you're forcing the program to traverse the entire list to append an element at the end). What you could do instead is to add each new element at the head of the list and reverse the final list:
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (List.rev xs, List.rev ys)
| (xs, ys, z :: zs) -> dcp_base (fst z :: xs) (snd z :: ys) zs;;
And actually, since OCaml is really strong, you don't need fst and snd at all:
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (List.rev xs, List.rev ys)
| (xs, ys, (x, y) :: zs) -> dcp_base (x :: xs) (y :: ys) zs;;
Proof:
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (List.rev xs, List.rev ys)
| (xs, ys, (x, y) :: zs) -> dcp_base (x :: xs) (y :: ys) zs;;
let descompact list =
match list with
| [] -> ([], [])
| xs -> dcp_base [] [] xs;;
descompact [(1, 4); (2, 5); (3, 6)];;
- : int list * int list = ([1; 2; 3], [4; 5; 6])

Finding the mode of an int list in SML and where it occurs without library functions

I'm trying to find the mode or value that occurs most frequently. I want a function like :
mode:' 'a list -> (''a * int) list
and it returns the mode and where it occurs, unless there is a tie then return all occurrences so something like:
mode([1,1,2,3,5,8]) ===> [(1,2)]
mode([1,3,5,2,3,5]) ===> [(3,2),(5,2)]
mode([true,false,true,true]) ====>[(true,3)]
I'm trying to do this without library functions in SML.
so far I got:
fun mode(L)=
if null L then nil
else if hd L= hd (tl L) then 1+mode(hd(tl L))
else mode(tl L);
I know this isn't right I guess I am curious on how you both keep the indices of where the mode occurs and what the mode is and return them as tuples in a list.
You're trying to solve an exercise in many parts with several easier exercises before it. Judging by your current progress, have you considered solving some very similar exercises that build up to the final goal? This is generally good advice when solving programming problems: Reduce your current problem to simpler problems and solve those.
I'd try and solve this problem first
Build a histogram : ''a list -> (''a * int) list over the elements of a list:
fun histogram [] = ...
| histogram (x::xs) = ...
Do this by inserting each x with its count into a histogram.
fun insert (x, []) = ...
| insert (x, (y, count) :: hist) = ...
And write some tests that you can execute once in a while.
Find the mode : ''a list -> ''a of a list:
fun mode xs = ... (histogram xs)
Do this by finding the element in the histogram with the biggest count:
fun findMax [] = ... (* what if the list/histogram is empty? *)
| findMax [(x, count)] = ...
| findMax ((x, count) :: (y, count) :: hist) = ...
and eventually try and solve this problem
When you have a good grasp of representing and navigating regular histograms recursively, you could create an annotated histogram : (''a * int * int list) list that doesn't just contain the frequency of each element, but also their positions in the input list:
fun histogram_helper ([], _) = ...
| histogram_helper (x::xs, i) = ... histogram_helper (xs, i+1) ...
Do this by inserting each x with its count and position i along with previously found positions is into a histogram:
fun insert (x, i, []) = ...
| insert (x, i, (y, count, is) :: hist) = ...
Find the (possibly multiple) mode : ''a list -> (''a * int list) list of a list:
fun mode xs = ... (histogram xs)
Do this by finding the (possibly multiple) element(s) in the histogram with the biggest count:
fun findMax ([], countMax, tmpModes) = ...
| findMax ((x, count, is) :: hist, countMax, tmpModes) = ...
with countMax : int being the frequency repeated in tmpModes : (''a * int * int list) list. Here countMax and tmpModes are accumulating result parameters. Do this by determining whether (x, count, is) should be thrown away in favor of all tmpModes, or it should be added to tmpModes, or it should be chosen in favor of all tmpNodes
I am curious on how you both keep the indices of where the mode occurs and what the mode is and return them as tuples in a list.
Yes, this is not trivial. Using my suggested division into sub-problems, answering this depends on whether we are in the histogram function or the findMax function:
In histogram you can store the indices as part of the tuple that contains the element and the frequency. In findMax, since you're potentially collecting multiple results, you need to keep track of both which frequency is the highest (countMax) and what the temporary modes of choice are (tmpModes); subject to replacement or addition in a later recursive call.
So to answer your question: In an accumulating parameter.
and a little feedback to your code snippet
fun mode(L)=
if null L then nil
else if hd L= hd (tl L) then 1+mode(hd(tl L))
else mode(tl L);
Use pattern matching instead of null, hd and tl:
fun count_4s [] = 0
| count_4s (x::xs) = (if x = 4 then 1 else 0) + count_4s xs
fun count_ns ([], _) = 0
| count_ns (x::xs, n) = (if x = n then 1 else 0) + count_ns (xs, n)
fun count_12 ([], ones, twos) = (ones, twos)
| count_12 (x::xs, ones, twos) =
if x = 1 then count_12 (xs, ones+1, twos) else
if x = 2 then count_12 (xs, ones, twos+1) else
count_12 (xs, ones, twos)
fun count_abc ([], result) = result
| count_abc (x::xs, ((a, ca), (b, cb), (c, cc))) =
count_abc (xs, if x = a then ((a, ca+1), (b, cb), (c, cc)) else
if x = b then ((a, ca), (b, cb+1), (c, cc)) else
if x = c then ((a, ca), (b, cb), (c, cc+1)) else
((a, ca), (b, cb), (c, cc)))
Building a histogram is sort of an extension to this where instead of a fixed value like 4, or a fixed amount of them like ones and twos, you have a whole list of them, and you have to dynamically look for the one you've got, x, and determine if it needs to be added to the histogram or incremented in the histogram.
The best way would be to do that in a helper function, so for example, if count_abc were made with a helper function,
fun insert_abc (x, ((a, ca), (b, cb), (c, cc))) =
if x = a then ((a, ca+1), (b, cb), (c, cc)) else
if x = b then ((a, ca), (b, cb+1), (c, cc)) else
if x = c then ((a, ca), (b, cb), (c, cc+1)) else
((a, ca), (b, cb), (c, cc)))
fun count_abc ([], result) = result
| count_abc (x::xs, result) =
count_abc (xs, insert (x, result))
only instead of the histogram representation
(''a * int) * (''a * int) * (''a * int)
you want
(''a * int) list
and insert should be recursive rather than how insert_abc is repetitive.

how to split a list into two lists in which the first has the positive entries and the second has non-positive entries-SML

I am a new to SML and I want to write a function splitup : int list -> int list * int list that given a list of integers creates from two lists of integers, one containing the non-negative entries, the other containing the negative entries.
Here is my code :
fun splitup (xs :int list) =
if null xs
then ([],[])
else if hd xs < 0
then hd xs :: #1 splitup( tl xs)
else hd xs :: #2 splitup( tl xs)
Here's the warning i get:
ERROR : operator and operand don't agree
ERROR : types of if branches do not agree
The function splitup(tl xs) should return int list * int list so i think my recursion should be all right.
What is the problem and how can i fix it ?
The problem is that
hd xs :: #1 splitup( tl xs)
and
hd xs :: #2 splitup( tl xs)
are lists – you can tell from the :: – not pairs of lists as the result should be.
For the non-empty case, you need to first split the rest of the list, then attach the head to the correct part of the result and add it the other part of the result in a pair.
It's also a good idea to get used to pattern matching, as it simplifies code lot.
Something like this:
fun splitup [] = ([], [])
| splitup (x::xs) = let (negatives, non_negatives) = splitup xs
in if x < 0
then (x :: negatives, non_negatives)
else (negatives, x :: non_negatives)
end
There is already List.partition: ('a -> bool) -> 'a list -> 'a list * 'a list, a higher-order library function that does this. In case you want to split up integers into (negative, non-negative):
val splitup = List.partition (fn x => x < 0)

First and last element of list OCaml

I am trying to get first and last element of the list in OCaml. I expect that my function will be like
'a list -> 'a * 'a
What I am trying to do is
let lista = [1;2;3;4;6;0];;
let rec first_last myList =
match myList with
[x] -> (List.hd lista,x)
| head::tail ->
first_last tail;;
first_last lista;;
Of course because of I made list as integer then I am doing this syntax like
*int list -> int * 'a
The point is that I dont have idea how to do this function for 'a.
Whats the direction?
The direction is to write two different functions first and last and implement the first_and_last function as:
let first_and_last xs = first xs, last xs
Another possibility with only one function:
let rec first_last = function
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You may prefer it like that:
let rec first_last myList = match myList with
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You can create two separate functions to return first element and last element, and then in your first_and_last function return a tuple (first_element, last_element).
let rec first_element list =
match list with
| [] -> failwith "List is empty"
| first_el::rest_of_list -> first_el
let rec last_element list =
match list with
| [] -> failwith "List is empty"
| [x] -> x
| first_el::rest_of_list -> last_element rest_of_list
You can create a helper function that has a base-case of the empty-list - for which it returns itself, and otherwise checks if the next recursive call will return an empty list. If it does, return the current element (which is by definition the last element in the list), and if it doesn't, return what was returned by the recursive call.
For the regular (non-helper) method, if the list is at least one element long (i.e. hd::tl = hd::[]) then you can just concatenate the list you got from the last function onto the head from ls.
It can be implemented as follow:
let rec last ls =
match ls with
| [] -> []
| hd::tl -> let next = last tl in
if next = [] then [hd]
else next
;;
let first_last ls =
match ls with
| [] -> failwith "Oh no!!!!! Empty list!"
| hd::tl -> hd::last tl
;;
Yet another take on this problem.
let first_last xs =
let rec last_non_empty = function
| [x] -> x
| _ :: xs' -> last_non_empty xs'
| [] -> failwith "first_last: impossible case!"
in
match xs with
| [] -> failwith "first_last"
| x::_ -> (x, last_non_empty xs)
Some properties of this implementation:
(1) it meets the specification 'a list -> 'a * 'a:
utop > #typeof "first_last";;
val first_last : 'a list -> 'a * 'a
(2) it works for singleton lists: first_last [x] = (x,x):
utop> first_last [1];;
- : int * int = (1, 1) utop> first_last ["str"];;
- : bytes * bytes = ("str", "str")
(3) it's tail-recursive (hence it won't cause stack overflow for sufficiently big lists):
utop > first_last (Array.to_list (Array.init 1000000 (fun x -> x+1)));;
- : int * int = (1, 1000000)
(4) it traverses the input list one time only; (5) it avoids creating new lists as it goes down the recursive ladder; (6) it avoids polluting the namespace (with the price of not allowing the reuse of a function like last).
And another rather simple variant, from the first principles (I was trying to illustrate "wishful thinking" in the spirit of the SICP book):
(* Not tail-recursive, might result in stack overflow *)
let rec first_last = function
| [] -> failwith "first_last"
| [x] -> (x,x)
| x :: xs -> (x, snd (first_last xs))
You could write it like this:
let first_last = function
| [] -> assert false
| x :: xs -> (x, List.fold_left (fun _ y -> y) x xs)
Or, if you are using the Base library, you could write in this way:
let first_last xs = (List.hd_exn xs, List.reduce_exn ~f:(fun _ y -> y) xs)
The basic idea is that List.fold_left (fun _ y -> y) x xs will compute the last element of x :: xs. You can prove this by induction on xs: if xs = [] then List.fold_left (fun _ y -> y) x [] = x, which is the last element of x :: []; moreover, if xs = x' :: xs' then List.fold_left (fun _ y -> y) x (x' :: xs') can be rewritten as List.fold_left (fun _ y -> y) x' xs', because List.fold_left f acc (x :: xs) = List.fold_left (f acc x) xs, hence we are finished, because this is the last element of x' :: xs' by our induction hypothesis.

Why is my function of type 'a list * 'a list -> 'b list?

I think I want it be be of type 'a list * 'a list -> 'a list .
intersection should return the intersection of two lists
sample input and output:
intersection ([1],[1]);
[1]
intersection ([1,2,3],[1,2]);
[1,2]
intersection ([[2,3],[1,2],[2,3]], [[1],[2,3]]);
[[2,3]]
my function:
fun intersection (l1, l2) = let
fun intersection_acc (acc, [], h::t) = []
| intersection_acc (acc, h::t, []) = []
| intersection_acc (acc, h::t, h2::t2) = if in_list (h, l2)
then intersection_acc (h::acc, t, l2)
else intersection_acc (acc, t, l2)
in intersection_acc ([], l1, l2)
end
I don't think in_list is the problem, but that looks like this:
fun in_list (x, []) = false
| in_list (x, y::r) = if x = y
then true
else in_list (x, r);
My guess is that you botched the base case in your accumulator function
intersection_acc (acc, h::t, []) = []
it should probably return something depending on acc:
intersection_acc (acc, h::t, []) = acc
The reason the 'b list shows up is because intersection will always return the empty list []. Since you don't use that empty list the compiler needs to be conservative and say that the list could be of any type.
In any case, your function seems to be fundamentally more confused. You actually want to do something like
result = []
for each item in list1:
if item in list2:
add item to result
return result
Translating this imperative code to a recursive function with an accumulator parameter:
fun go(acc, []) = acc
| go(acc, x::xs) =
if x in list2 then
go(x::acc, xs)
else
go(acc, xs)
For the full function:
fun intersect(list1, list2) = let
fun go(acc, []) = acc
| go(acc, x::xs) =
if x in list2 then
go(x::acc, xs)
else
go(acc, xs)
in go([], list1)

Resources