I'm doing a simple excercise for a Programming Languages class in SML, the exercise is to compute if a tree is balanced or not. The following code is what I thought would be a valid solution:
datatype IntTree = LEAF of int | NODE of (IntTree * IntTree);
fun balanced (LEAF l) = true
| balanced (NODE (LEAF l, NODE n)) = false
| balanced (NODE (NODE n1, NODE n2)) = balanced(n1) andalso balanced(n2)
| balanced (NODE (NODE n, LEAF l)) = false
| balanced (NODE (LEAF l1, LEAF l2)) = true;
However when I try to run this in the interpreter I get the following error:
stdIn:98.42-98.54 Error: operator and operand don't agree [tycon mismatch]
operator domain: IntTree
operand: IntTree * IntTree
in expression:
balanced n1
stdIn:98.63-98.75 Error: operator and operand don't agree [tycon mismatch]
operator domain: IntTree
operand: IntTree * IntTree
in expression:
balanced n2
But NODE should be of type IntTree, why doesn't this work?
I don't have an SML compiler right now, so I can't test this, but try changing balanced(n1) to (balanced (NODE n1)) (same with balanced(n2)).
Related
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.
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
I have the following qtree datatype:
datatype 'a qtree = Leaf of 'a
| Node of 'a branches
and 'a branches = Empty
| Branch of 'a qtree * 'a branches
An example tree is defined as follows:
val tr1 =
Node(Branch(Leaf(2),
Branch(Node(Branch(Leaf(6),
Branch(Leaf(5),Empty))),
Branch(Node(Empty),Empty))))
Here is a visual representation of tr1:
/|\
/ | \
2 / \
/ \
6 5
I have defined the following function tree_prod to find the product of the values in a qtree:
fun tree_prod(Leaf(n)) = n
| tree_prod(Empty) = 1
| tree_prod(Node(br)) = tree_prod(br)
| tree_prod(Branch(n, br)) = tree_prod(n) * tree_prod(br)
But I am receiving the following errors, which seem to occur due to a type mixup between qtree and branches:
stdIn:10.5-13.42 Error: parameter or result constraints of clauses don't
agree [tycon mismatch]
this clause: 'Z branches -> 'Y
previous clauses: 'X qtree -> 'Y
in declaration:
tree_prod =
(fn Leaf n => n
| Empty => 1
| Node br => tree_prod br
| Branch (<pat>,<pat>) => tree_prod <exp> * tree_prod <exp>)
stdIn:10.5-13.42 Error: parameter or result constraints of clauses don't
agree [tycon mismatch]
this clause: 'Z branches -> 'Y
previous clauses: 'X qtree -> 'Y
in declaration:
tree_prod =
(fn Leaf n => n
| Empty => 1
| Node br => tree_prod br
| Branch (<pat>,<pat>) => tree_prod <exp> * tree_prod <exp>)
stdIn:12.19-12.27 Error: operator and operand don't agree [tycon mismatch]
operator domain: [int ty] qtree
operand: [int ty] branches
in expression:
tree_prod br
stdIn:13.24-13.42 Error: operator and operand don't agree [tycon mismatch]
operator domain: [int ty] qtree
operand: [int ty] branches
in expression:
tree_prod br
How do I fix these errors?
Bonus: How do I implement this function using fold?
Your tree_prod attempts to apply to both types, which won't work - you need two functions.
If it's possible for you to change the type, you can use the fact that 'a branches is isomorphic to a list of 'a qtree (with Empty as nil and Branch as cons).
datatype 'a qtree = Leaf of 'a
| Node of ('a qtree) list
and then you can fold over the branches:
fun tree_prod (Leaf n) = n
| tree_prod (Node br) = List.foldl (fn (tree, acc) => tree_prod tree * acc) 1 br
val tr1 = Node [Leaf 2, Node [Leaf 6, Leaf 5], Node []]
- tree_prod tr1;
val it = 60 : int
If you don't want to change the type, you can write your own fold over 'a branches, following the same form as a list-fold.
Something like this might do it:
fun branch_fold f x Empty = x
| branch_fold f x (Branch t bs) = branch_fold f (f (t, x)) bs
and would give an almost identical "product":
fun tree_prod (Leaf n) = n
| tree_prod (Node br) = branch_fold (fn (tree, acc) => tree_prod tree * acc) 1 br
I have located the answer on my own. By dividing this into two separate functions, I am able to specify which types I am wanting to work with.
Here is the working solution:
fun tree_prod (Leaf(n)) = n
| tree_prod (Node(br)) = branches_prod(br)
and branches_prod (Empty) = 1
| branches_prod (Branch(n, br)) =
tree_prod(n) * branches_prod(br)
I'll start of by saying I'm very new to Haskell, so I haven't learned about things like Monads yet.
In Haskell I'm trying to make a type of tree that has numbers as the leaves and functions as the branches so the whole tree can act kind of like a calculator.
Here's my code so far. Currently instead of having functions as an input I'm just using characters.
data Tree3 = Leaf3 Int | Node3 Char Tree3 Tree3 deriving (Show)
-- I would like to replace this ^ Char somehow with a function.
evaluate :: Tree3 -> Int
evaluate (Leaf3 x) = x
evaluate (Node3 c m n) | c == '+' = evaluate m + evaluate n
| c == '-' = evaluate m - evaluate n
| c == '/' = evaluate m `div` evaluate n
| c == '*' = evaluate m * evaluate n
So my question is can I have an input of a function in the data structure (and what would the type be?)
Sorry for the probably confusing question, but thanks for any advice!
I would recommend writing your tree as:
data Tree = Leaf Int | Node (Int -> Int -> Int) Tree Tree
Note that you won't be able to derive Eq or Show, since Int -> Int doesn't implement either of those typeclasses (and it's impossible impractical to do so).
Then you can write your evaluate function as
evaluate :: Tree -> Int
evaluate (Leaf x) = x
evaluate (Node f l r) = f (evaluate l) (evaluate r)
which is much simpler!
You can make a tree to represent an expression like (1 + 2) * (3 * 4) as
expr :: Tree
expr = Node (*) (Node (+) (Leaf 1) (Leaf 2)) (Node (*) (Leaf 3) (Leaf 4))
Another way that would make it easier to prettier print your tree would be to use almost the same definition you have:
data Tree = Leaf Int | Node String Tree Tree
-- ^ String instead of Char
Then if you have Data.Map imported, you can create a map of functions to look up, but it makes your evaluate function a bit more complex since you introduce the possibility that your function won't be in your map. Luckily Haskell has some really handy tools for handling this elegantly!
import qualified Data.Map as Map
type Tree = Leaf Int | Node String Tree Tree deriving (Eq, Show)
type FuncMap = Map.Map String (Int -> Int -> Int)
evaluate :: FuncMap -> Tree -> Maybe Tree
evaluate funcs (Leaf x) = return x
evaluate funcs (Node funcName left right) = do
-- Use qualified import since there's a Prelude.lookup
f <- Map.lookup funcName funcs
l <- evaluate funcs left
r <- evaluate funcs right
return $ f l r
This will automatically result in Nothing if you try something like
evaluate (Map.fromList [("+", (+))]) (Node "blah" (Leaf 1) (Leaf 2))
since the function "blah" isn't in your FuncMap. Notice how we didn't have to do any explicit error handling of any kind thanks to Maybe's monad instance! If any of the lookups to the function map return Nothing, the whole computation returns Nothing without us having to think about it.
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 ::.