Standard ML error:operator and operand don't agree - sml

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".

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

SMLNJ: Operator & operand don't agree [tycon mismtach] - for list assignment

I have written the following function in SMLNJ:
fun f(id : int, l : int list list) =
let
val i : int = length(l) - 1
in
while i > 0 do
(
if (exists(id, List.nth(l, i))) then
List.hd(List.nth(l, i)) := 1
else();
i = i - 1
)
end;
The error received is as follows:
Error operator and operand don't agree [tycon mismatch]
operator domain: 'Z ref * 'Z
operand: int * [int ty]
in expression:
List.hd (List.nth (l,i)) := 1
I am aware that the operator domain is what the function expects while the operand is what is provided.
I presume this occurs as an int cannot be assigned to a list type. However, I am unclear as to how List.hdList.nth(l, i)) would result in anything other than an int.
Please advise on how I may fix this error and the supporting logic.
SML/NJ's error message does not make this terribly clear. If you were to put this code inside the Moscow ML REPL, and include the function contains which you've used but not defined, you'd get the following error:
! Toplevel input:
! List.hd(List.nth(l, i)) := 1
! ^
! Type clash: expression of type
! int list list
! cannot have type
! 'a ref list list
Your program fails because you're treating int values as if they were int ref values.
In functional programming you generally try to avoid mutable variables (ref values).
To elaborate on the problem you're having:
List.hd(List.nth(l, i)) := 1 means "Set the reference returned by List.hd(List.nth(l, i)) to 1. Since l is an int list list, then List.nth(l, i) returns the ith element of that (or crashes), which is an int list. Then List.hd(...) takes the 1st element of that (or crashes), which is an int. Not an int ref.
For this line to work, you'd need for l : int ref list list.
But you don't want that.
i = i - 1 is a boolean expression that returns true if i is equivalent to itself minus 1. This is not true for any int. You probably intend to subtract 1 from i and place the result in i, but you can't, because i is not a mutable variable, and the operator for updating a ref is called :=.
If your problem were to convert the list
val m = [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ]
into the list
val n = [ [ 1, 2, 3 ],
[ 1, 5, 6 ],
[ 1, 8, 9 ] ]
then a short way to do this would be to use List.map:
val n = List.map (fn row => 1 :: List.drop (row, 1)) m
A more manual way that practices recursion and pattern matching over iteration like while ... do (that only works if you have mutable variables) and partial functions like List.hd and List.nth (that might crash) could be:
fun f [] = []
| f (row::m) = (1 :: List.drop (row, 1)) :: f m
val n = f m
If you want a mutable version, consider the Array2 module instead of an int list list.
Here is one Array2 solution where the cursor is increased using recursion:
fun appulate f from to =
if from > to then ()
else (f from; appulate f (from+1) to)
fun f col m =
appulate (fn row => Array2.update (m, row, col, 1))
0 (Array2.nRows m - 1)
fun show m =
Array2.appi Array2.RowMajor (fn (_, col, c) =>
print (Int.toString c ^ (if col + 1 = Array2.nCols arr then "\n" else "" )))
{base=arr,row=0,col=0,nrows=NONE,ncols=NONE};
val m' = Array2.fromList m
val n' = f 0 m'
val _ = show n'
I realize that I haven't given any examples of a while ... do, or any collection of int refs on which one operates with ref, ! and :=.

Overload conflict in ML (SML/NJ)

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.

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 ::.

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).