union of list in ocaml without using library - ocaml

I have a assignment which requires writing a code to union list without using any library functions
this is my code
let rec union (l1:'a list) (l2:'a list) =
let rec f x l = match l with
| [] -> true
| hd::tl ->
if x = hd then false else f x tl
in
match l2 with
| [] -> l1
| hd::tl ->
if f hd l1 then
union hd::l1 tl
else
union l1 tl
but the compiler said that "This expression has type 'a but an expression was expected of type 'a list The type variable 'a occurs inside 'a list"
can somebody helps me to find out where did I do wrong? thanks

I think you just need some parentheses on the last line:
if f hd l1 then union (hd::l1) tl else union l1 tl
In OCaml function application (as in f x) has very high precedence. So without these parens the expression is interpreted as (union hd) :: (l1 tl).
(This code is pretty nice. Maybe rename f to something more descriptive such as notmem.)

Related

How to turn regular list into option list

let rec some_none list =
match list with
| [] -> list
| hd::tl ->
if hd = 0 then
[None] # some_none tl
else
[Some hd] # some_none tl;;
When I run this program it returns
Error: This expression has type int list but an expression was expected of type
'a option list
Type int is not compatible with type 'a option
How can I make it so that I am able to change a regular a' list to a' option list?
These two lines
match list with
| [] -> list
imply that the list returned by some_none has the same type as its argument.
Changing that line to
| [] -> []
solves the issue, since the left-hand and right-hand side are now unrelated.
A more subtle way (and not really useful here) is to use the as construct,
| [] as x -> x
because ... as x construct captures the type of the pattern rather than the type of the scrutinee (here list). However, this construction is mostly useful with polymorphic variants.
Also notice that your function some_none change neither the length of the list nor the order of the elements of the list. This means that it can be written as a map:
let some_none = List.map (fun elt -> ... )
Adding to what octachron has already said, there's a few style and performance issues with your code too.
First, it's unnecessary to create a new list in order to concatenate it using # when :: exists to prepend a single element to a list:
let rec some_none list =
match list with
| [] -> []
| hd::tl ->
if hd = 0 then
None :: some_none tl
else
Some hd :: some_none tl
Second, you can match on literal patterns directly instead of using comparison in an if expression within the branch:
let rec some_none list =
match list with
| [] -> []
| 0::tl -> None :: some_none tl
| hd::tl -> Some hd :: some_none tl
Third, you can use function to match directly on the last function argument:
let rec some_none = function
| [] -> []
| 0::tl -> None :: some_none tl
| hd::tl -> Some hd :: some_none tl
And fourth, you can use List.map to transform elements individually:
let some_none =
List.map (function 0 -> None | x -> Some x)
And now you have a function that is suddenly much easier to read and understand fully.

Ocaml Type error: This expression has type 'a * 'b but an expression was expected of type 'c list

I'm required to output a pair of lists and I'm not understanding why the pair I'm returning is not of the correct type.
let rec split l = match l with
| [] -> []
| [y] -> [y]
| x :: xs ->
let rec helper l1 acc = match l1 with
| [] -> []
| x :: xs ->
if ((List.length xs) = ((List.length l) / 2)) then
(xs, (x :: acc))
else helper xs (x :: acc)
in helper l []
(Please take the time to copy/paste and format your code on SO rather than providing a link to an image. It makes it much easier to help, and more useful in the future.)
The first case of the match in your helper function doesn't return a pair. All the cases of a match need to return the same type (of course).
Note that the cases of your outermost match are also of different types (if you assume that helper returns a pair).

Define reverse using fold left

I have this definition of fold left
let rec fold_left f lst u = match lst with
| [] -> u
|(h::t) -> fold_left f t ( f h u)
I have to define reverse using the fold_left above. I currently have
let reverse l1 = fold_left (fun x y -> y::x) l1 []
but I keep getting this error
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
What am I missing here?
You just have the accumulator and next item turned around (y::x instead of x::y). This works:
let reverse l1 = fold_left (fun x y -> x::y) l1 []

Type inferencing help in OCaml

How would I proceed with proving these two functions are well typed? I am a bit lost with this question.
let rec reduce f lst u =
match lst with
| [] -> u
| (h::t) -> f h (reduce f t u)
let rec forall2 p l1 l2 =
match (l1,l2) with
| ([],[]) -> true
| ([],_) -> false
| (_,[]) -> false
| ((h1::t1),(h2::t2)) ->
(p h1 h2) && (forall2 p t1 t2)
I won't give a fully-fledged solution since the question looks like an assignment.
To do the type-inference yourself, all you have to do is look at the source and make deductions. Then, from your deductions, deduce more and more types until all types are known, or until you've found a discrepancy.
To get you started:
In reduce, you're pattern-matching lst against patterns of type 'a list. Thus, lst must be typed as 'a list.
The values after each pattern must have the same type, so u has the same type as f h (reduce f t u).
Et cætera, et cætera...

OCaml error filter list using higher order functions

So I have this exercise:
filter (fun x -> x = 0) [(1,0);(2,1);(3,0);(4,1)];;
result int list [1;3]
So basically you have to match your x in fun with the second number in list and if its the same you create new list with the first number.
My solution but is wrong
let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [];;
I get the following error when i want to try the code:
Error: This expression has type int but an expression was expected of
type
int -> bool
I can't reproduce the problem you report. Here's what I see when I try your code:
$ ocaml
OCaml version 4.02.1
# let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [] ;;
val filter : 'a -> ('b * 'a) list -> 'b list = <fun>
# filter 0 [(1,0); (2,1); (3,0)];;
- : int list = [1]
There are no errors, but it gets the wrong answer. That's what I would expect looking at your code.
The error that you are getting is saying that somewhere the compiler is expecting an int -> bool function, but you are giving it an int. The reason you get this error is because you have an equality (f = snd x), where f is of type int -> bool and snd x is of type int. both arguments given to the equality must be of the same type. Instead, what you want to do is simply branch on the result of applying f to the second element of x, such as:
let rec filter f = function
| []->[]
| x::l -> if f (snd x) then fst x :: filter f l else [];;
That said, I would recommend using pattern matching instead of fst and snd, such as:
let rec filter f l =
match l with
| [] -> []
| (x,y)::l -> if f y then x :: filter f l else filter f l
Note that f y will return something of type bool, which will then determine which branch to take.
Altough Matts answer is right. It's good to just reuse existing functions instead of writing a special from the ground up:
[(1,0);(2,1);(3,0);(4,1)]
|> List.filter (fun (_, x) -> x = 0)
|> List.map fst