I have this simple function:
val CLC_seq=
fn (n) =>
(Cons (n, find_CLC_seq(COL_seq(n))))
When:
find_CLC_sqe is : int seq -> int;
COL_seq is: fn: int -> int seq;
The complier wrote:
Error: operator and operand don't agree
operator domain: int * (Unit -> int seq)
operand: int * int
in expression:
(Cons (n, find_CLC_seq(COL_seq(n))))
What is the reason? How can I solve it? Thank you.
Well, it's not clear what you're trying to do exactly, but the compiler is right to pick you up on it. find_CLC_seq returns an int, which means your Cons is trying to cons an int onto an int. That makes no sense, because cons is for adding an element to the front of a list (your Cons function is expecting to put an int on the front of a lazy sequence, a (Unit -> int seq)).
I don't know what CLC and COL are, but it looks like either:
Your definition of CLC_seq is wrong, because if find_CLC_seq is really meant to return an int, it doesn't make sense to be using it that way;
OR your definition of find_CLC_seq is wrong, and its return type should be int seq or a lazy sequence, as the name implies. In that case, the error is in a bit of code you haven't shown us.
Related
I'm new to SML and don't quite understand my issue, although I'm certain I'm at fault. First off, here are two short functions I am testing and their descriptions.
MakeInterval - Takes a natural number r, (also used for rp) and a natural number t, and returns the interval [t-r,t+r].
fun MakeInterval(r,rp,t) =
if r + rp < 0 then []
else t-r :: MakeInterval(r-1,rp,t);
E.g. MakeInterval(3,3,10) will return [7,8,9,10,11,12,13]. If you have a suggestion for getting rid of rp, please let me know. It's the only way I could think of to keep track of the original value of r while maintaining sorted order.
NotDivisible - Takes a natural number r, a list of natural numbers ts1 and another list of natural numbers ts2. Code using ts2 isn't yet written.
r specifies the lower and upper bounds of the interval, (same as MakeInterval), and ts1 is a list of numbers to be fed into map with the MakeInterval function.
fun NotDivisible(r, ts1, ts2) =
map (fn x => MakeInterval(r,r,x), ts1);
This function should return a list of intervals. E.g. NotDivisible(3, [10,20,30],
[2,4,6]) will return (for now) [[7..13], [17..23], [27..33]].
After I get this working, I will begin manipulating these lists to find which numbers out of these intervals are indivisible by any of the numbers in ts2.
But for now, my issue lies with the function definitions as I have them. MakeInterval is defined with no issues and I have tested it on it's own. This is the error I receive when attempting to define NotDivisible:
stdIn:5.33-5.71 Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z -> 'Y
operand: (int -> int list) * 'X
in expression:
map ((fn x => MakeInterval <exp>),ts1)
I've tried specifying all types manually to no avail. Everything makes sense to me logically, but clearly there is a syntax issue here that I am not following.
The issue with the above is the invocation of map, the function is curried
map : ('a -> 'b) -> 'a list -> 'b list;
so, a small change to the parentheses:
fun NotDivisible(r, ts1, ts2) = map (fn x => MakeInterval(r,r,x)) ts1;
gives you:
val NotDivisible = fn : int * int list * 'a -> int list list
I try to define function with the following protocol:
[(1,2), (6,5), (9,10)] -> [3, 11, 19]
Here is what I have now:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else (#1 hd(l)) + (#2 hd(l))::sum_pairs(tl(l))
According to type checker I have some type mismatch, but I can't figure out where exactly I'm wrong.
This code runs in PolyML 5.2:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else ((#1 (hd l)) + (#2 (hd l))) :: sum_pairs(tl l)
(* ------------^-------------^ *)
The difference from yours is subtle, but significant: (#1 hd(l)) is different from (#1 (hd l)); the former doesn't do what you think - it attempts to extract the first tuple field of hd, which is a function!
While we're at it, why don't we attempt to rewrite the function to make it a bit more idiomatic? For starters, we can eliminate the if expression and the clunky tuple extraction by matching on the argument in the function head, like so:
fun sum_pairs [] = []
| sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest)
We've split the function into two clauses, the first one matching the empty list (the recursive base case), and the second one matching a nonempty list. As you can see, this significantly simplified the function and, in my opinion, made it considerably easier to read.
As it turns out, applying a function to the elements of a list to generate a new list is an incredibly common pattern. The basis library provides a builtin function called map to aid us in this task:
fun sum_pairs l = map (fn (a, b) => a + b) l
Here I'm using an anonymous function to add the pairs together. But we can do even better! By exploiting currying we can simply define the function as:
val sum_pairs = map (fn (a, b) => a + b)
The function map is curried so that applying it to a function returns a new function that accepts a list - in this case, a list of integer pairs.
But wait a minute! It looks like this anonymous function is just applying the addition operator to its arguments! Indeed it is. Let's get rid of that too:
val sum_pairs = map op+
Here, op+ denotes a builtin function that applies the addition operator, much like our function literal (above) did.
Edit: Answers to the follow-up questions:
What about arguments types. It looks like you've completely eliminate argument list in the function definition (header). Is it true or I've missed something?
Usually the compiler is able to infer the types from context. For instance, given the following function:
fun add (a, b) = a + b
The compiler can easily infer the type int * int -> int, as the arguments are involved in an addition (if you want real, you have to say so).
Could you explain what is happening here sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest). Sorry for may be dummy question, but I just want to fully understand it. Especially what = means in this context and what order of evaluation of this expression?
Here we're defining a function in two clauses. The first clause, sum_pairs [] = [], matches an empty list and returns an empty list. The second one, sum_pairs ((a, b)::rest) = ..., matches a list beginning with a pair. When you're new to functional programming, this might look like magic. But to illustrate what's going on, we could rewrite the clausal definition using case, as follows:
fun sum_pairs l =
case l of
[] => []
| ((a, b)::rest) => (a + b)::sum_pairs(rest)
The clauses will be tried in order, until one matches. If no clause matches, a Match expression is raised. For example, if you omitted the first clause, the function would always fail because l will eventually be the empty list (either it's empty from the beginning, or we've recursed all the way to the end).
As for the equals sign, it means the same thing as in any other function definition. It separates the arguments of the function from the function body. As for evaluation order, the most important observation is that sum_pairs(rest) must happen before the cons (::), so the function is not tail recursive.
I have a pretty simple code that's supposed to transform a list of tuples (int * string), into two lists, one list of ints and one list of strings - basically a list of tuples into a tuple of lists.
fun unzip_single_int[] : int list = []
| unzip_single_int(x::xs) : int list =
x :: unzip_single_int(xs)
fun unzip_single_string[] : string list = []
| unzip_single_string(x::xs) : string list =
x :: unzip_single_string(xs)
fun unzip[] : (int list * string list) = ([], [])
| unzip([twopls]) : (int list * string list) =
let
val x : int list = unzip_single_int(twopls);
val y : string list = unzip_single_string(twopls); (* this is line 28 btw *)
in
(x, y)
end
And the error:
zip.sml:28.7-28.52 Error: operator and operand don't agree [tycon mismatch]
operator domain: string list
operand: int list
in expression:
unzip_single_int twopls
For some reason the compiler believes val y : string list = unzip_single_string(twopls) is referring to an int list.
Interestingly enough, when I switch the two around, when I change:
val x : int list = unzip_single_int(twopls);
val y : string list = unzip_single_string(twopls);
to
val y : string list = unzip_single_string(twopls);
val x : int list = unzip_single_int(twopls);
The error switches too:
zip.sml:28.7-28.47 Error: operator and operand don't agree [tycon mismatch]
operator domain: int list
operand: string list
in expression:
unzip_single_int twopls
For some reason, whatever the second call is, it's going to assume that its whatever the last call's type was. Why is it doing this? How do I overcome this? I made it very clear in the two other functions definitions that they are int lists and string lists respectively, so why does SML think that I'm sending it a string list when I clearly defined it as an int list ?
Thanks!
The answer to your question is type inference. You haven't given any type for twopls or an argument type for unzip, and you are calling unzip_single_int(twopls) when you make a value declaration for x. Therefore, SML infers that twopls is an int list, because the type of your function unzip_single_int is int list -> int list, which means it takes an int list as input and returns an int list.
After SML infers that twopls is an int list, you are trying to call unzip_single_string(twopls). However, the type of the function unzip_single_string is string list -> string list, therefore it expects an expression of string list as an input. But now twopls is an int list, so you get a type error.
However, your function definitions don't change anything about the list, they return the exact same list, I'm guessing you want them to return either the first or the second element in the tuple, so you should add that. Your unzip function is supposed to have the type (int * string) list -> int list * string list. Therefore, try to pattern match on the int * string elements you have in your list. Normally you would pattern match a list like x :: xs, but if you know the elements are tuples and if you want to access them, you can pattern match them like (num, str) :: xs, where num is an int variable and str is a string variable. You should be able to figure out the rest. Good luck!
I am new to OCaml, so I am learning the basics. I am writing a function that determines whether a list contains a given integer.
let rec int_member (x: int) (l: int list) : bool
begin match l with
| [] -> false
| hd :: rest -> x = hd || int_member rest x
end
as a test case...
let test (): bool =
(int_member 1 [1;2;3]) = true
;; run_test "contains 1 [1;2;3]" test
I am getting an error saying that "this expression has type int list but an expression was expected of type int". How can I fix this?
If you look at your recursive call, you should see that you're not passing the arguments quite right! Otherwise this code is quite good. (I see a missing =, and also using begin and end isn't very idiomatic OCaml here. You can just leave them out.)
int_member rest x
The first argument to int_member should be an int. You're passing an int list as the first argument. That's what the error message is complaining about.
You simply switched around the order of the arguments.
PS: The begin ... end in your code is superfluous.
I have to create a function about peano numbers defined as the following datatype:
datatype 'a peano = P of ('a -> 'a) * 'a -> 'a
val zero = P(fn (f, x) => x)
The function that I have to implement finds the succesive peano number of the peano parameter P(p). This is what I have written:
fun suc (P(p)) = case P(p) of P(fn(f,x)=>x) => P(fn(f,x)=>f(x));
The problem is that i get these errors:
stdIn:4.33-4.36 Error: syntax error: deleting FN LPAREN
stdIn:4.43 Error: syntax error found at RPAREN
I don't know what Im doing wrong. Please help!
There are a number of problems in this code. The one the compiler is whining about is that you have a function definition
fn (f,x) => x
on the left-hand side of a case arm, where only patterns are permitted.
Some other problems:
Redundant parentheses make the code hard to read (advice is available on removing them).
Your case expression is redundant; in the function definition
fun suc (P p) = ...
it should be possible just to compute with p without any more case analysis.
Since P carries a function, you will probably have an easier time if you write
fun suc (P f) = ...
and make sure that in the result, f is applied to a pair (as required by the datatype declarations).