SML Uncaught Exception Empty - exception

I am quite new to SML and am trying to implement a selection sort. I am running into an uncaught empty error however and can't seem to see why.
fun removeMin lst =
let
val (m, l) = removeMin(tl lst)
in
if null (tl lst) then
(hd lst, [])
else if hd lst < m then
(hd lst, tl lst)
else
(m, hd lst::l)
end;
fun selectionSort [] = []
| selectionSort lst =
let
val (m, l) = removeMin(lst)
in
m::selectionSort(l)
end;
I would appreciate suggestions as to where my mistake is and how to fix it.

There is no base case in your recursion. removeMin immediately
calls removeMin with the tail of lst. Eventually lst will be
the empty list and tl lst will fail with an Empty exception. So you
have to identify when you recursion should stop and add this case to
removeMin.
You have actually identified this base case in your function: if null (tl lst) then (hd lst, []). But this case should be checked right
before the recursive call. By reorganising your function and getting
rid of calls to hd and tl by using pattern matching constructs
this is what I get:
fun removeMin [] = raise Empty (* should not be called with an empty list *)
| removeMin [x] = (x, []) (* base case of the recursion *)
| removeMin (x :: tl) = let
val (m, l) = removeMin tl
in
if x < m
then (x, tl)
else (m, x :: l)
end;
fun selectionSort [] = []
| selectionSort lst = let
val (m, l) = removeMin(lst)
in
m :: selectionSort(l)
end;
selectionSort [3, 2, 12, 4];

Related

SML - Can't find where "uncaught exception Empty" is thrown in quicksort algorithm

I am trying to write a quicksort algorithm without using any List.nth functions. I've come up with this but when I try to test it, it ends up throwing an "uncaught exception Empty". I can't seem to find where this exception is thrown.
Here is my code:
(*returns last element in list*)
fun last (h::nil) = h
| last (h::lst) = last(lst)
| last _ = ~1;
(*returns middle element in list*)
fun middle (lst) =
let
fun middle_rec (_ :: []) (x :: _) = x
| middle_rec (_ :: _ :: []) (x :: _) = x
| middle_rec (_ :: _ :: xs) (_ :: ys) = middle_rec xs ys
| middle_rec _ _ = ~1
in
middle_rec lst lst
end;
(*return median of three elements*)
fun median(a,b,c) =
if ((b>a andalso a>c) orelse (c>a andalso a>b)) then a
else if ((a>b andalso b>c) orelse (c>b andalso b>a)) then b
else if ((a>c andalso c>b) orelse (b>c andalso c>a)) then c
else ~1;
(*partitions a list with one containing elements smaller than or equal to p and one with elements greater than p*)
fun partition([], p) = ([], [])
| partition(lst, p) =
let
fun part_rec ([], x::xs, y::ys, p) = (x::xs, y::ys)
| part_rec (lst, x, y, p) =
if hd(lst) <= p then part_rec(tl(lst), hd(lst)::x, y, p)
else part_rec(tl(lst), x, hd(lst)::y, p)
in
part_rec(lst,[],[],p)
end;
(*quicksort function*)
fun quicksort [] = []
| quicksort(x::xs) =
let
val (left, right) = partition(x::xs, median(x, middle(x::xs), last(x::xs)))
in
quicksort left # [x] # quicksort right
end;
quicksort([9, 4, 7, 2, 8, 5, 1, 6, 4, 3]);
Let's step through a very simple data set:
quicksort([1]);
val (left, right) = partition([1], median(1, middle([1]), last([1])))
val (left, right) = partition([1], median(1, 1, 1))
val (left, right) = partition([1], ~1)
val (left, right) = part_rec([1], [], [], ~1)
val (left, right) = part_rec([], [], [1], ~1)
And here we have a problem.
fun part_rec ([], x::xs, y::ys, p) = (x::xs, y::ys)
| part_rec (lst, x, y, p) =
if hd(lst) <= p then part_rec(tl(lst), hd(lst)::x, y, p)
else part_rec(tl(lst), x, hd(lst)::y, p)
The first pattern cannot apply, because the second argument is an empty list and thus cannot match with x::xs, so the second pattern must be applied. However, that means calling hd on an empty list, which will raise the Empty exception.

ML High-order function

Write an ML High-order function philter(f,x,L) that takes a function f and an element x and returns the list of all those elements y on list L such that f(x,y) = true.
Philter:((a’ * a’)→bool * a’ * a’list)→a’list
My code
fun filter p [] = [] | filter p (x::xs) =
if p x
then
x :: filter p xs
else
filter p xs;
filter (fn(x) => x<6) [6,3,0,1,8,5,9,3]; filter (fn(x) => x<6)
and i have diffrent val filter = fn : ('a -> bool) -> 'a list -> 'a list
any one can help me ?
Your function only takes a list and a function as argument where is the third argument e.g element x ??
As a consequence you check the condition p x and not p(x,y), from your description p should have type:
(a'* a') -> bool
Here is my implementation:
fun filter (p :('a * 'a -> bool) , _ ,[]) = []
| filter (p, x ,(y::ys))= if p (x,y) then y :: filter (p, x, ys)
else filter (p, x, ys);
and here is a tail-recursive implementation:
fun filter2 (p : ('a * 'a -> bool), x, L)=
let
fun filter3 (p, _, [], L) = rev L
| filter3 (p, x, (y::ys), L) = if p (x,y) then filter3 (p, x, ys, (y::L))
else filter3 (p, x, ys, L);
in
filter3 (p, x, L, [])
end
Example (see types and results):
val filter = fn : ('a * 'a -> bool) * 'a * 'a list -> 'a list
val filter2 = fn : ('a * 'a -> bool) * 'a * 'a list -> 'a list
val it = () : unit
- filter ((fn(x,y) => x<y), 4,[6,3,0,1,8,5,9,3]);
val it = [6,8,5,9] : int list
- filter2 ((fn(x,y) => x<y), 4,[6,3,0,1,8,5,9,3]);
val it = [6,8,5,9] : int list
By relying on the built-in List.filter, your philter could look like:
fun philter (f, x, L) = List.filter (fn y => f (x, y)) L

Putting last element of list in the first index "n" times SML

I'm trying to put the last element of a list in the front of the list while keeping the rest of the elements in the same order N times. I can do it once with this function, but I want to add another parameter to the function so that the function in called N times.
Code:
fun multcshift(L, n) =
if null L then nil
else multcshift(hd(rev L)::(rev(tl(rev L))));
Thanks
To make the parameter n work, you need recursion. You need a base case at which point the function should no longer call itself, and a recursive case where it does. For this function, a good base case would be n = 0, meaning "shift the last letter in front 0 times", i.e., return L without modification.
fun multcshift(L, n) =
if n = 0
then L
else multcshift( hd(rev L)::rev(tl(rev L)) , n - 1 )
The running time of this function is terrible: For every n, reverse the list three times!
You could save at least one of those list reversals by not calling rev L twice. E.g.
fun multcshift (L, 0) = L
| multcshift (L, n) =
let val revL = rev L
in multcshift ( hd revL :: rev (tl revL) , n - 1 ) end
Those hd revL and rev (tl revL) seem like useful library functions. The process of applying a function to its own output n times seems like a good library function, too.
(* Return all the elements of a non-empty list except the last one. *)
fun init [] = raise Empty
| init ([_]) = []
| init (x::xs) = x::init xs
(* Return the last element of a non-empty list. *)
val last = List.last
(* Shift the last element of a non-empty list to the front of the list *)
fun cshift L = last L :: init L
(* Compose f with itself n times *)
fun iterate f 0 = (fn x => x)
| iterate f 1 = f
| iterate f n = f o iterate f (n-1)
fun multcshift (L, n) = iterate cshift n L
But the running time is just as terrible: For every n, call last and init once each. They're both O(|L|) just as rev.
You could overcome that complexity by carrying out multiple shifts at once. If you know you'll shift one element n times, you might as well shift n elements. Shifting n elements is equivalent to removing |L| - n elements from the front of the list and appending them at the back.
But what if you're asked to shift n elements where n > |L|? Then len - n is negative and both List.drop and List.take will fail. You could fix that by concluding that any full shift of |L| elements has no effect on the result and suffice with n (mod |L|). And what if n < 0?
fun multcshift ([], _) = raise Empty
| multcshift (L, 0) = L
| multcshift (L, n) =
let val len = List.length L
in List.drop (L, len - n mod len) #
List.take (L, len - n mod len) end
There are quite a few corner cases worth testing:
val test_zero = (multcshift ([1,2,3], 0) = [1,2,3])
val test_empty = (multcshift ([], 5); false) handle Empty => true | _ => false
val test_zero_empty = (multcshift ([], 0); false) handle Empty => true | _ => false
val test_negative = (multcshift ([1,2,3,4], ~1) = [2,3,4,1])
val test_nonempty = (multcshift ([1,2,3,4], 3) = [2,3,4,1])
val test_identity = (multcshift ([1,2,3,4], 4) = [1,2,3,4])
val test_large_n = (multcshift [1,2,3,4], 5) = [4,1,2,3])
val test_larger_n = (multcshift [1,2,3,4], 10) = [3,4,1,2])

Recursive call in if expression - ocaml

module Dfs = struct
let rec dfslsts g paths final =
let l = PrimePath.removeDuplicates (PrimePath.extendPaths g paths)
in
let f elem =
if (List.mem "%d" (List.flatten final) = false) then (dfslsts g ["%d"] (List.flatten l)::final)
else final
in
List.iter f (Graph.nodes g)
end
Error: This expression has type string but an expression was expected of type int list
This error occurred when I called dfslsts function, which is recursive, inside the if condition.
The function dfslsts returns a list of lists.
If I try to replace the complex expression in if statement to
if (List.mem "%d" (List.flatten final) = false) then "%d"
else "%d"
then I get
Error: This expression has type 'a -> string
but an expression was expected of type 'a -> unit
Type string is not compatible with type unit
at List.iter line.
How do I solve this problem and are we allowed to call a recursive function inside the if expression.
This is the definition of my graph type:
module Graph = struct
exception NodeNotFound of int
type graph = {
nodes : int list;
edges : (int * int) list;
}
let makeGraph () =
{
nodes = [];
edges = [];
}
let rec isNodeOf g n = List.mem n g.nodes
let nodes g = g.nodes
let edges g = g.edges
let addNode g n =
let nodes = n::g.nodes and edges = g.edges in
{
nodes;
edges;
}
let addEdge g (n1, n2) =
if ((isNodeOf g n1) = false) then
raise (NodeNotFound n1)
else if ((isNodeOf g n2) = false) then
raise (NodeNotFound n2)
else
let nodes = g.nodes
and edges = (n1, n2) :: g.edges in
{
nodes;
edges;
}
let nextNodes g n =
let rec findSuccessors edges n =
match edges with
[] -> []
| (n1, n2) :: t ->
if n1 = n then n2::findSuccessors t n
else findSuccessors t n
in
findSuccessors g.edges n
let rec lastNode path =
match path with
[] -> raise (NodeNotFound 0)
| n :: [] -> n
| _ :: t -> lastNode t
end
module Paths = struct
let extendPath g path =
let n = (Graph.lastNode path) in
let nextNodes = Graph.nextNodes g n in
let rec loop path nodes =
match nodes with
[] -> []
| h :: t -> (List.append path [h]) :: (loop path t)
in
loop path nextNodes
let rec extendPaths g paths =
match paths with
[] -> []
| h :: t -> List.append (extendPath g h) (extendPaths g t)
(* Given a list lst, return a new list with all duplicate entries removed *)
let rec removeDuplicates lst =
match lst with
[]
| _ :: [] -> lst
| h :: t ->
let trimmed = removeDuplicates t in
if List.mem h trimmed then trimmed
else h :: trimmed
end
Any expression can be a recursive function call. There are no limitations like that. Your problem is that some types don't match.
I don't see any ints in this code, so I'm wondering where the compiler sees the requirement for an int list. It would help to see the type definition for your graphs.
As a side comment, you almost certainly have a precedence problem with this code:
dfslsts g ["%d"] (List.flatten l)::final
The function call to dfslsts has higher precedence that the list cons operator ::, so this is parsed as:
(dfslsts g ["%d"] (List.flatten l)) :: final
You probably need to parenthesize like this:
dfslsts g ["%d"] ((List.flatten l) :: final)

Exceptions handling in OCaml

I have to write the function try_finalyze f g y x of type : ('a -> 'b) -> ('b -> 'c) -> 'c -> 'a -> 'c
knowing that:
1. if an exception is raised by f x the returned value has to be y
2. if f x doesn't raise any exception we have to return the result of g applied on f x
exception E
let try_finalyze f g y x = try g (f x) with E -> y;;
val try_finalyze : ('a -> 'b) -> ('b -> 'c) -> 'c -> 'a -> 'c = <fun>
1.Is it right how I treated the problem?
2.In this context what will do the following function:
fun f -> try_finalyze f (fun x-> Some x) None
I don't see the role of a function like (fun x-> Some x)
The answer to your first question is - not really. According to your specification function should catch any exception, not only your exception E. Maybe I'm misreading, but it will be better use the following definition:
let try_finalize f g y x = try g (f x) with exn -> y
As for the second part of the question, there're several ways in OCaml to signal an error. The two most common are:
Raise an exception
Return a value of an option type
The former variant is syntactically lighter, the later doesn't allow a caller to ignore the error condition. Sometimes you need to switch from one variant to an another. Suppose you have a function that raises an exception, and you would like to create a function with the same behavior, but returning an option value. Let's give it a name:
let with_option f = try_finalize f (fun x-> Some x) None
Then we can, for example, convert a List.hd to a function that returns an option type, depending on whether the list is empty or not:
let head x = with_option List.hd x
This function will have type 'a list -> 'a option, compare it with List.hd type 'a list -> 'a, the former will not allow to ignore the empty list case. When applied to an empty list, it will return a None value:
# head [];;
- : 'a option = None
If you write
let try_finalize f g y x = try g (f x) with _ -> y
Your function will return y if f doesn't raise an error but g does, which is not what you said you want.
To ensure that you catch only errors from f you should put f x alone in the try block:
let try_finalize f g y x =
let z = try Some (f x) with _ -> None in
match z with
| Some z -> g z
| None -> y
Exceptions may be considered bad style in a purely functional code, that's why you may want to transform a function that may raise an exception such as List.assoc : 'a -> ('a * 'b) list -> 'b into a function that does the same thing but returns an option.
That's what
let with_option f = try_finalize f (fun x-> Some x) None
does.
If I understand the problem statement correctly, I think I would do this :
let try_finalize f g y x =
try
let v = f x in g v
with _ -> y
As for question 2, suppose you have a function f that takes a value of type v and computes a result of type r. This :
fun f -> try_finalize f (fun x-> Some x) None
returns a function that tries to apply f. If it succeeds (i.e. no exception is thrown), it returns Some r. Otherwise, it returns None. Basically, it transforms a function that may throw an exception into a function that will not throw anything. The new function returns a r option instead of a r.
Maybe like this but the function doesn't have anymore the required type
let try_finalyze f g y x = match f x with
|E -> y
| _ -> g (f x) ;;