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).
Related
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
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 :=.
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".
I am stuck with this SML assignment. I am trying to create a compound function (fun compound n f). It's supposed to apply the function f on itself for n times for example, compound 3 f will equal to f(f(f(x))). I got it to work except for case where n is zero. I asked the professor but he won't tell me a direct answer. He tried to give me an hint that "what's function times zero?" I still can't figure that out either. Can stackoverflow figure it out?
Thanks.
My code:
fun compound n f =
if n < 2 then
if n = 0 then fn x => f x else fn x => f x
else fn x => f(compound (n-1) f(x));
example:
val fnc = fn x => x + 1; (* example function to be used *)
compound 5 fnc(10); (* will return 15 which is correct*)
compound 0 fnc(10); (* returns 11, should be 10 *)
Answer:
fun compound n f =
if n < 2 then
if n = 0 then fn x => x else fn x => f x
else fn x => f(compound (n-1) f(x));
I won't give you the final answer because I don't like to upset teachers ;) However, I'll try a derivation that I believe you'll find easy to complete.
Let's start from a very simple case. Let's "reimplement" function application, i.e., let's write a function that takes a function and an argument and apply the first param to the second one:
fun apply f a = f a
Let's use a contrived function, that increments integers, for testing:
- fun inc n = n + 1;
val inc = fn : int -> int
- inc 1;
val it = 2 : int
- apply inc 1;
val it = 2 : int
Now, let's write apply2, a function which takes a function and an argument and applies the param function two times to the argument:
fun apply2 f a = f (f a)
Let's test it with inc:
- apply2 inc 1;
val it = 3 : int
Seems to be working. As you might expect, we'd now implement apply3, apply4 and so on. Let's see some of them at once:
fun apply f a = f a
fun apply2 f a = f (f a)
fun apply3 f a = f (f (f a))
fun apply4 f a = f (f (f (f a)))
It looks like we can rewrite later ones in terms of the earlier ones:
fun apply2 f a = f (apply f a)
fun apply3 f a = f (apply2 f a)
fun apply4 f a = f (apply3 f a)
We can even rewrite apply:
fun apply f a = f (apply0 f a)
Remember the previous definition of apply, they're equivalent:
fun apply f a = f a
So, what should apply0 be?
fun apply0 f a = ...
What is the base case for this algorithm? i.e. at what value of n does the recursion terminate? When it terminated what do you return? Think about what you would want to return if f is not applied to x. In the context of your example, if fnc is applied to 10 zero times, what should be returned?
fun compound n f =
(* If n equals the termination value, then return the base case*)
if n = ?
else fn x => f(compound (n-1) f(x));
There is a pattern here that exists in the base case for recursive algorithms. For example, what is the sum of a list with no elements? Or, what is the length of a list with no elements?
So I'm working on a function to find some valid arithmetic operations to a target number from an int list. It's not allowed to use throw/callac. Only add and mul are valid arithmetic operations here and they are left associative.
datatype operation = ADD | MULT
(* find_op: int -> int list -> (operatino list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k()
| find_op x [y] s k = if x=y then s([]) else k()
| find_op x (y1::y2::ys) s k =
let
val add = find_op x ((y1+y2)::ys) (fn a => s(ADD::a)) k
val mul = find_op x ((y1*y2)::ys) (fn a => s(MULT::a)) k
in
need some work here
end
The function should work like below:
Given list [1,1,2,~1] and target number ~4, the accpeted operation list should be [ADD,ADD,MULT] or [ADD,MULT,MULT], because (((1+1)+2)*~1) = ((1+1)2~1) = ~4. But [MULT,ADD,MULT] will not be valid since (((1*1)+2)*~1) = ~3.
I'm confused how to check whether returned results are k(). Using = to check return value is not possible since it is polymorphic. Is there any method to handle this?
What you have to do is use the two strategies, first try reducing the numbers via ADD, then reduce the numbers via MULT, but sequentially. In order to do this you need to provide a custom failure continuation (k) to the result of the first chosen strategy. If that strategy fails, you try the second strategy in the continuation failure.
You can't try both strategies at the same time and have them both succeed. The function type does not permit returning multiple correct answers. For that you'd need the success continuation's type to be operation list list.
datatype operation = ADD | MULT
fun opToString ADD = "ADD"
| opToString MULT = "MULT"
(* find_op: int -> int list -> (operation list -> 'a) -> (unit -> 'a) -> 'a *)
fun find_op x [] s k = k ()
| find_op x [y] s k = if x = y then s [] else k ()
| find_op x (y1 :: y2 :: ys) s k =
let
(* You need a custom failure continuation that tries the MULT variant
* if the ADD one fails.
*)
fun whenAddFails () =
find_op x ((y1 * y2) :: ys) (fn a => s (MULT :: a)) k
val add =
find_op x ((y1 + y2) :: ys) (fn a => s (ADD :: a)) whenAddFails
in
add
end
fun test () =
let
val opList = [1,1,2,~1]
val target = ~4
fun success ops =
"success: " ^ (String.concatWith " " (List.map opToString ops))
fun failure () =
"couldn't parse numbers as an operation list"
in
find_op target opList success failure
end