F# function argument type mismatch - list

I am using following function to make tuples of two lists in F#
let rec MyOwnZipper xs ys =
match xs,ys with
| [],l| l,[] -> []
| x1::rest, y1::yrest -> (x1, y1) :: (MyOwnZipper rest yrest)
it works fine when calling function with lists of integers like
System.Console.WriteLine( MyOwnZipper [1; 2; 3] [4; 5; 6] )
The problem comes when I change arguments to string
System.Console.WriteLine( MyOwnZipper [1; 2; 3] ["Hello"; "World"; "Peace"] )
I get the following error
error FS0001: This expression was expected to have type
int
but here has type
string
exit status 1

This happens because of the first case of the match expression:
| [],l| l,[] -> []
Here, the identifier l gets bound either to the first list, or to the second list. Since an identifier cannot have two different types at once, the compiler concludes that the lists must have the same type. Therefore, if you try to call the function with differently typed lists, you get a type mismatch error, quite expectedly.
To fix the problem, break the case in two separate cases:
let rec MyOwnZipper xs ys =
match xs,ys with
| [],l -> []
| l,[] -> []
| x1::rest, y1::yrest -> (x1, y1) :: (MyOwnZipper rest yrest)

Related

why is a definition like this not producing an error in OCaml?

let f (x :: []) = [1;2];;
I don't understand the structure of this function.
Normally a function is declared like this:
let <function name> <arguments> = <function definition> But here
we give the function f a constant as an argument, namely [x], and then do
nothing with this argument. Instead, we assign the constant [1;2] to the function f?
To illustrate why having patterns in a function definition is useful, here are few examples of exhaustive patterns in arguments. The first common case is tuple:
let f (x,y) = x + y
In the code above,(x,y) is a pattern that binds the first and second element of a couple to the x and y variable respectively.
There is an equivalent construction for records
type vec2 = {x: float; y:float}
let f { x; _ } { y; _ } {x=x'; y = y' } = x +. y +. x' + y'
In this case {x; _}, {y; _ }, { x=x'; y=y'} are both exhaustive patterns.
For ordinary variants, it is less frequent to have useful and exhaustive patterns, but this can happen:
let f (x::_, _ | [], x) = x
Here, in this case we are either extracting the first element of the list in the first element of the tuple if the list is not empty, or the second element of the tuple.
Those cases are more frequent when using GADTs or empty types that makes it possible to have some branches of an algebraic not inhabited for a specific subtype.
For instance, the pattern in
type empty = |
let f (None:empty option) = ()
is exhaustive because the only possible value of the type empty option is None.
utop # let f x :: [] = [1;2];;
Error: Syntax error
This does give me an error. The following will compile.
let f (x :: []) = [1; 2]
But produces a warning about incomplete pattern match, because a list can have zero or any number of elements. A list with one element is just one specific example.
utop # let f (x :: []) = [1; 2];;
Line 1, characters 6-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_::_
val f : 'a list -> int list = <fun>
It's worth noting that [x] is not a constant in a function like this. It is binding the name x to the one element in the list, whatever that happens to be.
Consider:
utop # let foo [x] = x;;
Line 1, characters 8-15:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_::_
val foo : 'a list -> 'a = <fun>
utop # foo [42];;
- : int = 42
Of course, this is a silly function, since x is never used by the function. You might just have written the following, using _ to indicate a value that we don't care enough about to give a name to.
let foo [_] = [1; 2]

OCaml assertion fail

Hey everyone I'm new to OCaml and having some problems. So I'm trying to do a recursive function that takes a non-empty list and returns the last element. My list can be any data type though.
Here is what I have right now and it's currently failing on the assertion statement saying "This expression has type int but an expression was expected of type int list.
let rec last l = match l with
[] -> []
|[x] -> [x]
|_::t -> last t ;;
assert(last [1; 2; 3; 4] = 4);;
assert(last ["a"; "b"; "c"; "d"] = "d");;
I often find that a good way to deal with this kind of type errors, is to explicitly annotate the function with the type I want it to have - in this case, I expect that you want the first line to be something like this:
let rec last: 'a list -> 'a = fun l -> match l with
With that, the error changes to:
File "1/hest.ml", line 5, characters 9-10:
5 | |[x] -> [x]
^
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
Which is a more helpful error. The problem is, as #PatJ writes in his answer, that as you have written the function you actually return a list with one element (or no elements, when the list is empty), but your usage of the function seems to indicate that you just want the last element.
You can either:
change your usage of the function, so the asserts compare with [4] and ["d"] instead of just the values.
change the function to return Some x and None instead of [x] and [], and change the asserts to assert against Some 1 and Some "d".
change the function to return x instead of [x] and throw an exception in the empty list case - that would be: failwith "empty list"
I think the second solution is the most natural one.
If you go for exceptions, then renaming the function to last_exn would convey to users that they have to beware that the function might throw.
The problem comes from the fact that your function is indeed returning a list, as can be seen in those two lines:
[] -> []
|[x] -> [x]
You want the second line to be |[x] -> x. Of course, you also need to handle the case of an empty list and effectively return something. You can either have it raise an exception, use an option type or have the caller specify a default value.
In this kind of cases, it's better to use an option type:
let rec last_opt l =
match l with
| [] -> None
| [x] -> Some x
| _x::t -> last_opt t
let () =
assert (last_opt [1; 2; 3; 4] = Some 4);
assert (last_opt ["a"; "b"; "c"; "d"] = Some "d"); (* Note that here you could use chars, i.e. 'a', 'b' etc. instead of strings "a", "b" etc. *)
assert (last_opt [] = None)
If you really don't want an option type, you should handle the empty case with care :
let rec last l =
match l with
| [] -> raise (Failure "last")
| [x] -> x
| _x::t -> last t

Ocaml: add up all the integers in an int list and output it as an int Option

. Write a function that takes an integer list and return sum of all elements of the list. If the list is empty then return None.
This is my code now:
let rec sum (xs: int list) =
match xs with
| [] -> None
| [x] -> Some x
| hd::tl -> let m = (hd + (sum tl)) in
Some m
;;
The problem is that I can't seem to find a way to add up the last element without getting an error.
This is my error.
Error: This expression has type int but an expression was expected of type 'a option.
Your recursive call to sum does indeed return an int option. You know this because you're the author of the function, and you coded it up to return that type :-) You can either write a helper function that returns an int, or you can extract the int from the return value of sum, something like this:
let tlsum =
match sum tl with
| None -> (* figure this part out *)
| Some n -> (* figure this part out *)
You can define the addition of two int option.
let sum l =
let (+) a b =
match (a,b) with
| (None,x) | (x,None) -> x
| (Some x,Some y) -> Some (x+y)
in
let convert a = Some a in
let opt_l=List.map convert l in
List.fold_left (+) None opt_l
Test
# sum [];;
- : int option = None
# sum [1;2];;
- : int option = Some 3
That looks like an assignment so I'll be vague:
The easiest way to do that is probably to first define a function of type int list -> int that returns the "normal" sum (with 0 for the empty case). That function will be recursive and 0 will correspond to the base case.
Then write another function of type int list -> int option that checks whether its argument is empty or not and does the right thing based on that.
Trying to write the recursion directly probably is not a good idea since there are two cases when you will need to handle []: when it's the only element in the list, and when it's at the end of a nonempty list.

I need to make an # using cons in OCAML

My teacher says we cant use appends # in our program so im going to write my own recursive function for it.
Here is what i have so far:
(my own appends function)
let rec appends a b =
match a with
| [] -> b
| hd::[]-> hd::b
| hd::tl-> (what i need help on)
;;
im not sure how to add just the last element of a to b if a is a list with multiple elements and then call appends on the first part since you can only remove the first element of a list with the ::
any advice would be appreciated
Something that might help is to think more functionally, i.e., to think of the code as a definition of what it means in principle to append two lists. This is as opposed to thinking of the code as a set of actions to be performed. Sometimes this helps, especially when coding in a functional language.
So, your first case says: if a is empty, the result of appending a and b is just b itself.
Your second case says: if a is a list of one element hd, the result of appending a and b is a list that consists of hd added to the beginning of b.
You're looking for a general definition for appending that works for any non-empty list a. The key insight is that your definition can be recursive, i.e., it can use your appends function.
So here is a proposed definition: if a is a list whose head is hd and whose tail is tl, the result of appending a and b is a list whose head is hd and whose tail is tl appended to b.
(This in fact gives the whole thing away. I hope it doesn't spoil the exercise for you.)
Late answer, but consider that [1; 2; 3] is a syntactic convenience for 1 :: 2 :: 3 :: []. If you wanted to append [4; 5; 6] to [1; 2; 3] you need to replace the [] with [4; 5; 6].
You need to turn append [1; 2; 3] [4; 5; 6] into 1 :: 2 :: 3 :: [4; 5; 6].
If I just wanted to write an identity function for a list, it'd look like:
let rec list_id lst =
match lst with
| [] -> []
| x::xs -> x :: list_id xs
Now, you just need to pass in a second list, and have the base case return that instead. A locally scoped recursive function with access to b solves this nicely.
let append a b =
let rec aux = function
| [] -> b
| x::xs -> x :: aux xs
in
aux a

pairing an int with a list of ints in OCaml

I am using OCaml to write a function that takes a list of ints and an int element and returns a list of pairs where the first element of every pair is the int element and the second element of the pair is a member from the list. For example, let say I have the number 1 and the list [10; 20; 30] as inputs. I like the function to return [(1, 10); (1, 20); (1, 30)]. I wrote the following function:
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)];;
I am getting the following error:
Characters 59-120:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
_::_::_ val f : int list -> int -> (int * int) list = <fun>
What am I missing?
Here is your code
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)]
In your match, you listed two cases: [] and [x].
Your first case is [], you mean empty, no problem.
Your second case is [x], what did you want to mean? In OCaml, it means a list with only one element.
How about the cases where there are more than one element?
For any if else or match with, you should include all cases.
When you fix this problem, you will soon find you really missed something more there.
Here is the correct code:
let rec f e l =
match l with
| [] -> []
| x::[] -> [(e,x)]
| x::tl -> (e,x)::(f e tl)
Note
above code is not tail-recursive and you normally should consider about it, I will leave that to you.
you don't need ;; if you write your code in file and compile the file
You don't need to declare types in most cases and that is one of the best thing ocaml has.
Your patterns match lists of length 0 ([]) and of length 1 ([x]). The compiler is telling you that there are other lengths that a list might have, so your pattern is probably wrong (which is true).
I might note that it's not an error to get an empty list as an argument. Thinking this way will make it much harder to answer the problem. If you get an empty list, the correct answer is an empty list of pairs.
let rec f e = function
| [] -> []
| x::tl -> (e,x)::f e tl
Or
let f e = List.map (fun x -> (e,x))
Test
# f 1 [];;
- : (int * 'a) list = []
# f 1 [10;20;30];;
- : (int * int) list = [(1, 10); (1, 20); (1, 30)]