Ordering a BST in alphabetic order and returning it as a list in SML - sml

I have this tree
datatype 'a newarbolbin =
Vacio
| Nodo of 'a newarbolbin * 'a * 'a newarbolbin;
and this functions to order it however I want to:
fun preOrden2 (Vacio) = []
| preOrden2 (Nodo(L, r, R)) = [r] # preOrden2(L) # preOrden2(R);
fun inOrden2 (Vacio) = []
| inOrden2 (Nodo(L, r, R)) = inOrden2(L) # [r] # inOrden2(R);
fun postOrden2 (Vacio) = []
| postOrden2 (Nodo(L, r, R)) = postOrden2(L) # postOrden2(R) # [r];
And the tree I have to sort is the following:
val diccionario : (string * string) newarbolbin = Vacio
The first string being a Spanish word and the right one a translation to English, and I have to sort it in alphabetical order with the Spanish words, the English ones don't really matter, the function I did for this, which obviously doesn't work because I probably overthought again, is the following:
fun listar_orden_alfabetico (Vacio) = []
| listar_orden_alfabetico (Nodo(L, (esp, ing), R)) =
if esp < listar_orden_alfabetico(L) then
(if listar_orden_alfabetico(L) < listar_orden_alfabetico(R) then
preOrden2(Nodo(L, (esp, ing), R))
else
preOrden2(Nodo(R, (esp, ing), L)))
else
(if listar_orden_alfabetico(R) < listar_orden_alfabetico(L) then
postOrden2(Nodo(L, (esp, ing), R))
else
postOrden2(Nodo(R, (esp, ing), L)))
And just in case, this is the error I'm having:
stdIn:44.53-48.132 Error: operator and operand do not agree [overload - bad instantiation]
operator domain: 'Z[OL(<)] * 'Z[OL(<)]
operand: 'Z[OL(<)] * 'Y list
in expression:
esp < listar_orden_alfabetico L
stdIn:45.59-46.129 Error: operator and operand do not agree [overload - bad instantiation]
operator domain: 'Z[OL(<)] * 'Z[OL(<)]
operand: 'Y list * 'Y list
in expression:
listar_orden_alfabetico L < listar_orden_alfabetico R
stdIn:47.59-48.131 Error: operator and operand do not agree [overload - bad instantiation]
operator domain: 'Z[OL(<)] * 'Z[OL(<)]
operand: 'Y list * 'Y list
in expression:
listar_orden_alfabetico R < listar_orden_alfabetico L
I know it means that I'm using the function wrong, but I really don't know what to do.
After some changes, I added a new function I came up with this:
fun stringdend (Vacio) = "zzzzzzzzzzzzzzzzz"
| stringdend (Nodo (L,(esp,ing),R)) = esp;
fun listar_orden_alfabetico (Vacio) = []
| listar_orden_alfabetico (Nodo(L,(esp,ing),R)) = if esp<stringdend(L)
then (if stringdend(L)<stringdend(R)
then preOrden2(Nodo(L,(esp,ing),R))
else preOrden2(Nodo(R,(esp,ing),L)))
else (if stringdend(R)<stringdend(L)
then postOrden2(Nodo(L,(esp,ing),R))
else postOrden2(Nodo(R,(esp,ing),L)));
val diccionario = Nodo(Nodo(Nodo(Vacio,("hola","hi"),Vacio),("comer","eat"),Nodo(Vacio,("agucate","eggplant"),Vacio)),("agua","water"),Nodo(Vacio,("sadico","sadistic"),Vacio));
the result is not quite right and I still don't know why
val it =
[("agua","water"),("comer","eat"),("hola","hi"),("agucate","eggplant"),
("sadico","sadistic")] : (string * string) list

The problem is that your "binary search tree" input is not a binary search tree; its nodes are not ordered.
(The ordering of the nodes is what makes it a "search" tree.)
If you use a correctly constructed search tree - for instance,
val diccionario =
Nodo(
Nodo(
Nodo(Vacio,("agua","water"),Vacio),
("agucate","eggplant"),
Nodo(Vacio,("comer","eat"),Vacio)),
("hola","hi"),
Nodo(Vacio,("sadico","sadistic"),Vacio));
an inorder traversal gives the alphabetical ordering:
- inOrden2 diccionario;
val it =
[("agua","water"),("agucate","eggplant"),("comer","eat"),("hola","hi"),
("sadico","sadistic")] : (string * string) list
(You really should implement functions that construct a BST correctly, and not do it by hand.)

You want the function listar_orden_alfabetico to return a list. If so, how is this comparison supposed to work?
esp < listar_orden_alfabetico(L)
esp is a string, and listar_orden_alfabetico(L) is meant to be a list. There is no < operator that can compare those two data types.

Related

Issue with a tycon mismatch

Working on a homework assignment that essentially takes a tree, the declaration of which is:
datatype a BinTree =
Leaf of a
| Node of a BinTree * a BinTree;
and returns a tuple of an int height of tree and a list of values which were stored at that deepest portion of the tree.
fun deepest tree =
case tree of
Leaf(n) => [n]
| Node(l, r) => if #1(deepest l) > #1(deepest r) then ((#1(deepest l) + 1), #2(deepest l)) else
if #1(deepest l) < #1(deepest r) then ((#1(deepest r) + 1), #2(deepest r)) else
(1, #2(deepest l) # #2(deepest r));
Trying to test this code, I come up with the following error message:
stdIn:43.1-47.35 Error: types of rules don't agree [tycon mismatch]
earlier rule(s): 'Z BinTree -> 'Z list
this rule: 'Z BinTree -> [+ ty] * 'Y list
in rule:
Node (l,r) =>
if (fn <rule>) (deepest <exp>) > (fn <rule>) (deepest <exp>)
then (<exp> <exp> + 1,(fn <rule>) (deepest <exp>))
else if <exp> <exp> < <exp> <exp>
then (<exp> + <exp>,<exp> <exp>)
else (1,<exp> # <exp>)
stdIn:21.2-47.35 Error: right-hand-side of clause doesn't agree with
function result type [type mismatch]
expression: 'Z list
result type: {1:[+ ty], 2:'X list; 'Y}
in declaration:
deepest =
(fn tree =>
(case tree
of <pat> => <exp>
| <pat> => <exp>))
stdIn:1.2-47.35 Error: unresolved flex record (need to know the names of ALL
the fields
in this context)
type: {1:[+ ty], 2:'Y list; 'Z}
While I do understand that its a type conflict, I can't find what the conflict is, nor how to fix it. Any help would be appreciated.
This
earlier rule(s): 'Z BinTree -> 'Z list
comes from the leaf case ([n]), which makes it a function from trees to lists.
And this:
this rule: 'Z BinTree -> [+ ty] * 'Y list
comes from the node case, making it a function from trees to pairs of "a type that supports addition" and lists.
The remaining errors are caused by SML not being able to deduce what #1 and #2 mean in the presence of that conflict.
Your base case is wrong – it should be a pair, not a list.
The depth in that pair should be 1, and the depth should not be 1 in the case where both subtrees are equally deep.
You're also computing the deepest values three times for each subtree in the worst case, and two in the best case.
It's better to recurse only once for each subtree.
Something like this:
fun deepest (Leaf n) = (1, [n])
| deepest (Node (l, r)) =
case deepest l of (dl, ll) =>
case deepest r of (dr, lr) =>
if dl > dr then (dl + 1, ll)
else if dr > dl then (dr + 1, lr)
else (dl + 1, ll # lr)
While I also prefer case-of like molbdnilo for writing this function, here is an example of using let-in-end to demonstrate that they can both be used when the result is a product (tuple). Since there are three cases in the if-then-else with three distinct outcomes (dl > dr, dr > dl and dl = dr), using Int-compare may be preferable:
fun deepest (Leaf n) = (1, [n])
| deepest (Node (l, r)) =
let val (lcount, ls) = deepest l
val (rcount, rs) = deepest r
in case Int.compare (lcount, rcount) of
GT => (lcount + 1, ls)
| LT => (rcount + 1, rs)
| EQ => (lcount + 1, ls # rs)
end

OCaml - why is my function of type 'a list list -> ... rather than 'a list?

let rec slice l i k = match l with
h::t -> if (k == 0) then h
else if (i == 0) then h # (slice t 0 (k-1))
else slice t (i-1) (k-1);;
When I enter slice [1; 2; 3; 4] 1 2;; I get:
Error: This expression has type int but an expression was expected of type 'a list
however if I enter slice [[1]; [2]; [3]; [4]] 1 2;; it works as intended. I don't understand why OCaml thinks l is a list of lists of 'a, and not just a standard list of 'a?
I see two problems. In your first case you return h. But you should be returning a list, and h is the first element of your list.
In your second case you use the # operator, which expects a list on both sides. But h is the first element of your list, not a list. You can fix this by using :: instead of #.
Other problems:
I don't see a place where you handle an empty list l.
You should use = rather than ==. The == operator in OCaml is for very special purposes only. For day-to-day equality comparisons you want to use =.

Quicksort in SML operator and operand don't agree error

I am trying to write a quicksort function of type
'a list * ('a * 'a -> bool) -> 'a list
but for some reason I am getting:
'a list -> ('a * 'a -> bool) -> 'a list
Here is my code for the function:
fun quicksort xs f = let
fun qs [] = []
| qs [x] = [x]
| qs (p::xs) = let
val (less, more) = List.partition (fn x => f (x, p)) xs
in
qs less # p :: qs more
end
in
qs xs
end
When I call the function I get this error:
stdIn:73.1-73.18 Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z list
operand: int list * (int * int -> bool)
in expression:
quicksort (L, op <)
I realize that I must be passing it in wrong, but I just can't see my mistake. So, my question is what is going on here in which I get this error while trying to pass in my list and operator?
You could simple change:
fun quicksort xs f = let
to:
fun quicksort (xs,f) = let
since you want quicksort to have as parameters a tuple (xs,f).

Less-than function in Standard ML

I'm trying to make a function in SML that takes a list and an int and returns a list of all elements that are less than the int int * int list -> int list I wrote the following code:
- fun less (e, L) =
= map (fn a => if a < e then a else []) L;
also with the following code it doesnt work also:
- fun less (e, L) =
= map (fn a => if a < e then a) L;
and the error im getting is :
stdIn:22.15-22.38 Error: types of if branches do not agree [overload]
then branch: 'Z
else branch: 'Y list
in expression:
if a < e then a else nil
I think the problem is with the else part but I dont know what to put in it to work, anybody have any suggestion? I should use either map, foldl, or foldr functions.
EDIT:
- fun less (e, L) =
= let
= val acc = []
= in
= foldr (fn a => if a < e then a::acc else acc) acc L
= end;
still gives me error, the following error :
stdIn:241.3-241.54 Error: operator and operand don't agree [overload]
operator domain: 'Z * 'Y -> 'Y
operand: 'X -> 'X list
in expression:
foldr (fn a => if <exp> < <exp> then <exp> :: <exp> else acc)
The error message is clear; since a has type int and [] has type 'a list, their types are mismatched.
The problem is you chose the wrong high-order function for the task. The filter on List structure is best suited here:
fun less (e, L) = filter (fn a => a < e) L
You could use recursion to implement less explicitly, or use foldl/foldr to accumulate filtered lists. However, map seems irrelevant here.
EDIT:
I will give a hint about using foldl/foldr. You start with empty list as the accumulator. Prepend an element to the accumulator whenever that element is smaller than e; otherwise, return the accumulator.
EDIT 2:
You forgot to pass acc as an argument in the lambda function:
fun less (e, L) = foldr (fn (a, acc) => if a < e then a::acc else acc) [] L
And the let..in..end part is redundant because you use [] as the accumulator only.

unfolding lists in ML

hello everyone I'm trying to write function which can unfold int in the list from any depth, for example if I have following bigList: [12, [34], [11,[1]]] I want to receive
[(1,12),(2,34),(3,11),(4,1)]
first element in tuple is the depth and the second is the number
I wrote this code:
datatype 'a bigList = Empty of unit
| Element of 'a
| List of 'a bigList list;
local
fun unfolder( Empty , n ) = []
| unfolder( (Element l)::ls, n ) = (n, l)::unfolder( ls, n )
| unfolder( (List l)::ls, n) = unfolder( l, n + 1)::unfolder(ls, n)
in
fun flat list = unfolder(list, 1)
end;
every time I receive the following error:
Standard ML of New Jersey v110.71 [built: Thu Sep 17 08:50:14 2009]
- datatype 'a bigList = Element of 'a | Empty of unit | List of 'a bigList list
stdIn:9.5-11.69 Error: data constructor Empty used without argument in pattern
stdIn:11.33-11.69 Error: operator and operand don't agree [tycon mismatch]
operator domain: (int * 'Z) list * (int * 'Z) list list
operand: (int * 'Z) list * (int * 'Z) list
in expression:
unfolder (l,n + 1) :: unfolder (ls,n)
-
thanks in advance for any help
data constructor Empty used without argument in pattern
You defined Empty as Empty of unit, which means you need to use it as Empty (), which is pretty pointless. To use it as just Empty, you need to define it as Empty without the of unit.
unfolder (l,n + 1) :: unfolder (ls,n)
The type of :: is 'a * ['a] -> ['a], which means that the left operand must be a single element and the right operand a list. In the above both operands are a list, so you get a type error.
To concatenate two lists use the # operator, not ::.