Overload conflict in ML (SML/NJ) - sml

I have written the following piece of code for ML:
fun get_digits (0, s) = s
| get_digits (d, s) = get_digits( d div 10, (d mod 10) :: s)
| get_digits n = get_digits( n div 10, [n mod 10] );
But it gives me the following error:
Error: Operator and operand do not agree (overload conflict)
operator domain: [mod ty] * [mod ty]
operand: ([mod ty] * [mod ty] list) * [int ty]
in expression
n div 10
Error: Operator and operand do not agree (overload conflict)
operator domain: [mod ty] * [mod ty]
operand: ([mod ty] * [mod ty] list) * [int ty]
in expression
n mod 10
Can someone explain what this means and what changes i should make? Thanks in advance

Your first two cases say that the argument of get_digits is a pair of an integer and a list.
Then your third case tries to apply div and mod to such a pair, which doesn't work.
Since you can't define a function that takes either a number or a pair as its argument, you need to use two functions:
fun get_digits' (0, s) = s
| get_digits' (d, s) = get_digits' (d div 10, (d mod 10)::s);
fun get_digits n = get_digits' (n div 10, [n mod 10]);
You can define the helper function locally in get_digits, of course.

Related

operator and operand do not agree [tycon mismatch]

I am trying to write a function in sml that takes in a list of pairs and returns pair of two list of all the elements
Meaning if the input is [(1, 2.0), (2, 3.0)]
The output should be ([1, 2], (2.0, 3.0))
fun divide nil = (nil , nil)
| divide [(a, b)::nil] = ([a], [b])
| divide [(a, b)::myTl] =
let
val (x, y) = divide myTl
in
(a::x, b::y)
end
;
Never the less the sml interpreter returns the following err
Error: operator and operand do not agree [tycon mismatch]
operator domain: ('Z * 'Y) list list
operand: ('Z * 'Y) list
in expression:
divide myTl
The error message you're seeing is because you've (inadvertently) declared a function with domain ('a * 'b) list list due to your input patterns, so your recursive call is not well typed.
The most straightforward fix is to correct for the incorrect use of [ ] around the argument to the function---this is making a singleton list, instead of just grouping the pattern. Thus you'd want to use ( ) instead.
fun divide nil = (nil , nil)
| divide ((a, b)::nil) = ([a], [b])
| divide ((a, b)::myTl) =
let
val (x, y) = divide myTl
in
(a::x, b::y)
end
Your second base case is also extraneous, so we could further revise this to
fun divide [] = ([], [])
| divide ((a, b)::xs) =
let
val (x, y) = divide xs
in
(a::x, b::y)
end

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

Product of Tree Elements SMLNJ

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)

Standard ML error:operator and operand don't agree

I want to write a function number_before_reaching_sum that takes an int called sum, and return an int n such that the first n elements of the list add to less than sum, but the first n + 1 elements of the list add to sum or more.
Here's my code
fun number_before_reaching_sum(sum:int,lists:int list)=
let
val sum_list=0
val n=0
in
let fun list_compute(sum_list:int,lists2:int list,n:int)=
let val sum_list2=sum_list+(hd lists2)
in if sum_list2>=sum
then (sum_list2,n+1)
else (#1 list_compute(sum_list2,tl lists2,n+1),#2 list_compute(sum_list2,tl lists2,n+1))
end
in #2 list_compute(sum_list,lists,n)
end
end
The error message prints out:
hw1_1.sml:67.14-67.97 Error: operator and operand don't agree [type mismatch]
operator domain: {1:'Y; 'Z}
operand: int * int list * int -> 'X
in expression:
(fn {1=1,...} => 1) list_compute
hw1_1.sml:67.14-67.97 Error: operator and operand don't agree [type mismatch]
operator domain: {2:'Y; 'Z}
operand: int * int list * int -> 'X
in expression:
(fn {2=2,...} => 2) list_compute
hw1_1.sml:69.11-69.44 Error: operator and operand don't agree [type mismatch]
operator domain: {2:'Y; 'Z}
operand: int * int list * int -> int * int
in expression:
(fn {2=2,...} => 2) list_compute
I cannot figure out why (#1 list_compute(sum_list2,tl lists2,n+1),#2 list_compute(sum_list2,tl lists2,n+1))and #2 list_compute(sum_list,lists,n)
this 2 lines are wrong.
f g(x,y) gets parsed as (f g) (x,y), not f (g (x,y)). So you want to add parentheses like this:
#1 (list_compute (sum_list2,tl lists2,n+1))
Otherwise it tries to apply #1 to the function list_compute. The error message is the compiler telling you "#1 wants a tuple, but you gave it a function instead".

error in the SML of NJ

hello everyone I have this snippet of the code:
local
fun NTimesF(f, n:int) =
if n = 1 then fn (x) => f(x)
else fn (x) => f(NTimesF(f, n - 1)(x))
in
fun compList f n = if n = 0 then []
else (NTimesF(f, n)) :: (compList f n-1)
end;
I need to write program which receives some function f and integer n and produce list of functions such as [f1, f2, ... fn] <- fn is the composition of the function n times but every time I receive an error:
- stdIn:7.11-7.46 Error: operator and operand don't agree [literal]
operator domain: ('Z -> 'Z) * ('Z -> 'Z) list
operand: ('Z -> 'Z) * int
in expression:
NTimesF (f,n) :: (compList f) n - 1
stdIn:6.6-7.46 Error: right-hand-side of clause doesn't agree with function result type [literal]
expression: int -> _ list
result type: int -> int
in declaration:
compList = (fn arg => (fn <pat> => <exp>))
-
can somebody please help me, thanks in advance
Because function application has higher precedence than the - operator, compList f n-1 is parsed as (compList f n) - 1, which is obviously not what you want.
You need to write compList f (n-1).