I'm new to Ocaml and i'm trying to write a recursion function.
The function take a list of pairs and return a pair of lists, for example
[(1, 4); (2, 3); (5, 9); (6, 10)]) -> ([1; 2; 5; 6], [4; 3; 9; 10])
But the compiler say that: Error: This expression has type 'a list * 'b list
but an expression was expected of type 'a list
in the line (unzip (List.tl m))
Can someone explain why I have this error please? And is there anyway to fix this? Thank you very much!
let rec unzip m =
if List.length m = 0 then
([], [])
else
((fst (List.hd m)) :: (unzip (List.tl m)), (snd (List.hd m)) :: (unzip (List.tl m)))
in
unzip m;;
For any recursion, you have to note that the output type will be always the same.
Let's see your unzip function.
[(1, 4); (2, 3); (5, 9); (6, 10)]) -> ([1; 2; 5; 6], [4; 3; 9; 10])
Simply say, the return type of unzip is def a pair (tuple), and each element is a list, correct?
Then let's see your code
let rec unzip m =
if List.length m = 0 then
([], [])
else
((fst (List.hd m)) :: (unzip (List.tl m)), (snd (List.hd m)) :: (unzip (List.tl m)))
in
unzip m;;
You have two branches. First branch is returning ([], []). Ok, in terms of return type, it is correct as it is a pair with two empty lists and matches the return type described above.
The second branch
((fst (List.hd m)) :: (unzip (List.tl m)), (snd (List.hd m)) :: (unzip (List.tl m)))
is it correct?
It is a pair with two elements, no problem, then let's see the first element:
(fst (List.hd m)) :: (unzip (List.tl m))
You are trying to add (fst (List.hd m)) to the head of (unzip (List.tl m)).
But you can only add something to a list by using ::, so ocaml supposes (unzip (List.tl m)) is a list, right?
But it is a unzip function application, apparently described in the beginning, your unzip is not returning a list, but a pair (tuple).
So ocaml doesn't understand and thus complain.
The above is just to answer your question about the type problem. But your code has more problems.
1. incorrect use of in
Suppose you have a function f1. You can image it as the mother function, which means it can be used directly. Also in f1, you can declare another function or variable (or more formally, a binding). Only when you declare a binding inside a function, you use let...in.... If you only have the mother function, you don't use in, because in where?
In your unzip, you only have one function or binding which is unzip itself and it is in top level. So in is not necessary.
2. incorrect logic of recursion
I don't know how to explain to you about recursion here, as it needs you to read more and practise more.
But the correct code in your idea is
let rec unzip = function
| [] -> ([], [])
| (x,y)::tl ->
let l1, l2 = unzip tl in
x::l1, y::l2
If you are chasing for better or a tail-recursive version, here it is:
let unzip l =
let rec unzip_aux (l1,l2) = function
| [] -> List.rev l1, List.rev l2
| (x,y)::tl -> unzip_aux (x::l1, y::l2) tl
in
unzip_aux ([],[]) l
The error comes from the fact that (unzip ...) returns a pair of lists ('a list * 'b list), which you try to manipulate as a list when you write (fst ..) :: (unzip ...).
This would all be written much more nicely if you used pattern-matching. Skeleton:
let rec unzip = function
| [] -> ...
| (x,y) :: rest ->
let (xs, ys) = unzip rest in ...
Related
Who can help? I am a beginner in OCaml, I am trying to perform an action of unpacking sets. Having a set [(1, 4); (2, 5); (3, 6)] I want to get the exit [(1,2,3), (4,5,6)]. I am using a script that I tested with Haskell and it worked, but in OCaml, it does not show the result. Where am I going wrong? I could not figure out where my mistake is. Thx.
let fst num1 num2 =
match num1, num2 with
| (x, y) -> x;;
let snd num1 num2 =
match num1, num2 with
| (x, y) -> y;;
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (xs, ys)
| (xs, ys, z :: zs) -> dcp_base (xs # [fst z]) (ys # [snd z]) zs;;
let descompact list =
match list with
| [] -> ([], [])
| xs -> dcp_base [] [] xs;;
The problem is your redefinition of fst and snd. They're not needed, as they're already defined in the standard library and in scope with exactly those names. But they're also wrong. Your implementation takes two arguments and selects either the first or second in a roundabout way by creating an intermediary tuple, instead of a singe tuple argument directly. Therefore, when you apply it to a single tuple argument it will return a partially applied function expecting the second argument.
You can fix the problem just by removing the definitions of fst and snd from your code, but if you absolutely want to reimplement it, it ought to look something more like this:
let fst (x, _) = x;;
let snd (_, y) = y;;
Your fst and snd functions are actually strange since you take two arguments to return the first one or the second one. I guess you wanted to get the first or second element of a pair so you should write (from most detailed to least detailed)
(* too much details *)
let fst num = match num with (x, y) -> x
let snd num = match num with (x, y) -> y
(* let's use the wildcards *)
let fst num = match num with (x, _) -> x
let snd num = match num with (_, y) -> y
(* do we really need num? *)
let fst = function (x, _) -> x
let snd = function (_, y) -> y
(* do we really need to match on a single pattern? *)
let fst (x, _) = x
let snd (_, y) = y
And it should work.
As a side note, fst and snd already exist in the standard library but it's never wrong to try implementing them yourself
Second side note, appending at the end of a list is usually not advised (not tail recursive, you're forcing the program to traverse the entire list to append an element at the end). What you could do instead is to add each new element at the head of the list and reverse the final list:
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (List.rev xs, List.rev ys)
| (xs, ys, z :: zs) -> dcp_base (fst z :: xs) (snd z :: ys) zs;;
And actually, since OCaml is really strong, you don't need fst and snd at all:
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (List.rev xs, List.rev ys)
| (xs, ys, (x, y) :: zs) -> dcp_base (x :: xs) (y :: ys) zs;;
Proof:
let rec dcp_base list1 list2 list3 =
match list1, list2, list3 with
| (xs, ys, []) -> (List.rev xs, List.rev ys)
| (xs, ys, (x, y) :: zs) -> dcp_base (x :: xs) (y :: ys) zs;;
let descompact list =
match list with
| [] -> ([], [])
| xs -> dcp_base [] [] xs;;
descompact [(1, 4); (2, 5); (3, 6)];;
- : int list * int list = ([1; 2; 3], [4; 5; 6])
I implemented it using continuation. I think this is tail recursive but I'm told it's not. Why isn't it tail recursive?
let rec zip_tr fc sc l1 l2 = match l1, l2 with
| [], [] -> sc []
| [], _ -> fc (List.length l2)
| _, [] -> fc (List.length l1)
| h1::t1, h2::t2 ->
zip_tr fc (fun l -> sc ((h1, h2) :: l)) t1 t2
Isn't this tail recursive? Do the failure/success continuations have an effect effect on tail recursiveness?
There's only one recursive call in your code, and it is in tail position. So I would say your function is tail recursive.
It does build up a fairly large computation in the sc argument. However, the call to sc is in tail position also. In my tests, the function works for very large lists without running out of stack space.
If I try your function on two copies of a very long list (100,000,000 elements), it terminates successfully (after quite a long time). This suggests to me that it really is tail recursive.
Here is the session with the long list:
# let rec zip_tr fc sc l1 l2 = . . . ;;
val zip_tr :
(int -> 'a) -> (('b * 'c) list -> 'a) -> 'b list ->
'c list -> 'a = <fun>
# let rec mklong accum k =
if k <= 0 then accum
else mklong (k :: accum) (k - 1);;
val mklong : int list -> int -> int list = <fun>
# let long = mklong [] 100_000_000;;
val long : int list =
[1; 2; 3; 4; 5; ...]
# let long_pairs =
zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) long long;;
val long_pairs : (int * int) list =
[(1, 1); (2, 2); (3, 3); (4, 4); (5, 5); ...]
# List.length long_pairs;;
- : int = 100000000
If you change your code so that the call to sc is not a tail call:
zip_tr fc (fun l -> (h1, h2): sc l) t1 t2
It generates the result in reverse order, but it also fails for long lists:
# zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) [1;2] [3;4];;
- : (int * int) list = [(2, 4); (1, 3)]
# zip_tr (fun _ -> failwith "length mismatch")
(fun x -> x) long long;;
Stack overflow during evaluation (looping recursion?).
I'm don't know enough about OCaml code generation to explain this in detail, but it does suggest that your code really is tail recursive. However it's possible this depends on the implementation of closures. For a different implementation, perhaps the generated compuation for sc would consume a large amount of stack. Maybe this is what you're being told.
Using a tail-recursive function, you build something which is like a linked-list of continuations, by wrapping each sc inside another anonymous function; then, you call the resulting continuation.
Fortunately, your continuations are also tail-recursive, since the result of one call to sc directly gives the result of the anonymous closure. That explains why you don't have stack overflows when testing it.
The possible drawback of this function is that it allocates a lot of closures (but still with linear complexity) before starting to do any actual work, which is not what is usually done.
An advantage of this approach is that the success continuation is only called when both your lists are known to have the same size; more generally, compiling code to continuations is something that is interesting to know when working with languages (so your effort is not wasted).
If the function is part of some course, you are probably expected to directly build the result list while traversing your input lists, in a tail-recursive way, without delaying the work in continuations.
I am a new to SML and I want to write a function splitup : int list -> int list * int list that given a list of integers creates from two lists of integers, one containing the non-negative entries, the other containing the negative entries.
Here is my code :
fun splitup (xs :int list) =
if null xs
then ([],[])
else if hd xs < 0
then hd xs :: #1 splitup( tl xs)
else hd xs :: #2 splitup( tl xs)
Here's the warning i get:
ERROR : operator and operand don't agree
ERROR : types of if branches do not agree
The function splitup(tl xs) should return int list * int list so i think my recursion should be all right.
What is the problem and how can i fix it ?
The problem is that
hd xs :: #1 splitup( tl xs)
and
hd xs :: #2 splitup( tl xs)
are lists – you can tell from the :: – not pairs of lists as the result should be.
For the non-empty case, you need to first split the rest of the list, then attach the head to the correct part of the result and add it the other part of the result in a pair.
It's also a good idea to get used to pattern matching, as it simplifies code lot.
Something like this:
fun splitup [] = ([], [])
| splitup (x::xs) = let (negatives, non_negatives) = splitup xs
in if x < 0
then (x :: negatives, non_negatives)
else (negatives, x :: non_negatives)
end
There is already List.partition: ('a -> bool) -> 'a list -> 'a list * 'a list, a higher-order library function that does this. In case you want to split up integers into (negative, non-negative):
val splitup = List.partition (fn x => x < 0)
I am new to Ocaml and am writing code to substitute elements in nested Ocaml lists. My code is as follows:
type 'a sexp = S of 'a | L of 'a sexp list
My substitution function(it replaces all occurrences of element a with b in nested lists) is as follows:
let rec subst a b list = match list with
| [] -> list
| S s :: t -> if s = a then (S b) :: (subst a b t) else (S s) :: (subst a b t)
| L l :: t -> (subst a b l) :: (subst a b t)
Despite multiple attempts(for nearly 6 hours), I have not been able to compile this code.. Please help!
Can I suggest to first write a function subst of type 'a -> 'a -> 'a sexp -> 'a sexp instead? It would read
let subst x y sexp =
let rec visit = function
| S z -> S (if z = x then y else z)
| L sexps -> L (List.map visit sexps)
in
visit sexp
and arguably nicely and idiomatically captures the idea of recursing over an sexp.
Now, to obtain a function to operate on lists rather than single sexps, you can easily define a function subst_list of type 'a -> 'a -> 'a sexp list -> 'a sexp list:
let subst_list x y sexps = List.map (subst x y) sexps
Even nicer is to abstract away from substitution and have a more generally applicable function map of type ('a -> 'b) -> 'a sexp -> 'b sexp for performing structure-preserving mappings of sexps:
let map f sexp =
let rec visit = function
| S x -> S (f x)
| L sexps -> L (List.map visit sexps)
in
visit sexp
And then define subst in terms of map and subst_list, as before, in terms of subst:
let subst x y sexp = map (fun z -> if z = x then y else z) sexp
let subst_list x y sexps = List.map (subst x y) sexps
Note: using an F# compiler here; I don't have an OCaml compiler on this computer.
The last line of your subst function has an error: It should be as follows:
| L l :: t -> L (subst a b l) :: (subst a b t)
So the complete code would look like this:
type 'a Sexp =
| S of 'a
| L of 'a Sexp list
let rec subst (a) (b) (lst : 'a Sexp list) =
match lst with
| [] -> lst
| S s :: t -> if s = a then (S b) :: (subst a b t) else (S s) :: (subst a b t)
| L l :: t -> L (subst a b l) :: (subst a b t)
let test () =
let (lst : int Sexp list) = [S 1; L [S 2; L [S 3]; S 4]; S 5]
let a = 2
let b = 3
subst a b lst
The output of test() is
[S 1; L [S 3; L [S 3]; S 4]; S 5]
The reason is that your function subst returns a 'a Sexp list. If you omit the L constructor from the last line, then subst a b l is of type 'a Sexp list, which you are attempting to cons with another list of type 'a Sexp list. This does not work.
Nor was this your intention, since you wanted to end up with an entity of type 'a Sexp list, which means you must cons an element of type 'a Sexp with a list of type 'a Sexp list. By specifying the L constructor, you are creating an element of type 'a Sexp list, which you can now cons with the rest of the list.
It looks like your function subst is supposed to return something of type 'a sexp list. That's what the first and second match cases return.
In the third match case, then, your returned value is:
(subst a b l) :: (subst a b t)
Since your function returns 'a sexp list, this type doesn't make a lot of sense. The head of the list is of type 'a sexp list and the tail of the list is also of type 'a sexp list. It's very difficult to come up with any lists that have this kind of structure. I think what you want is for the head of the list to be of type 'a sexp.
If you want the head of the list to be of type 'a sexp, you need some way of packaging up a list of things into a single 'a sexp. If this isn't enough of a hint, look at your L constructor. That's exactly what it does.
I am trying to write a general function in F# that would return all the permutations of a list. I was trying to accomplish this using a recursive algorithm inspired by the java version here
But on the final line of the recursive function, I get the error given in the comments. I am guessing this is something to do with collating the output produced when the recursive loop exits (the output of if(Array.length <= 1) then being executed) with the rest Array.Map function.
I would greatly appreciate it if someone could give an explanation of why this error is happening and how I can go about fixing it.
let GetPermutationsOfList inputList =
let rec innerLoop firstPart secondPart =
if (Array.length secondPart) <= 1 then
[| Array.append firstPart secondPart |]
else
let SliceAtMarkerElement m =
let currentMarkerElement = secondPart.[m]
let everythingBeforeMarkerElement = secondPart.[0 .. m - 1]
let everythingAfterMarkerElement = secondPart.[m+1 .. ]
let newSecondPartList = Array.append everythingBeforeMarkerElement everythingAfterMarkerElement
let newFirstPartList = Array.append firstPart [|currentMarkerElement|]
(newFirstPartList, newSecondPartList)
[|for i in 0 .. ((Array.length secondPart) - 1) -> i|] |>
Array.map(fun c -> SliceAtMarkerElement c) |>
// The following line gives the error
// "Type Mismatch. Expecting a 'a but given a 'a[] The resulting type would be infinite when unifying "a' and "a[]"
Array.map(fun d -> innerLoop (fst d) (snd d))
innerLoop Array.empty (List.toArray inputList)
Assume that your function's indentation is correct, the error message is quite informative. In the innerLoop function, Array.append firstPart secondPart should return 'b []. However, the last line Array.map(fun d -> innerLoop (fst d) (snd d)) forces it to return 'b [] [], which couldn't be unified with 'b [].
I think you would like calculate permutations in each innerLoop and concatenate these results afterwards. You have to use Array.collect instead of Array.map:
[|for i in 0 .. (Array.length secondPart)-1 -> i|]
|> Array.map (fun c -> SliceAtMarkerElement c)
|> Array.collect (fun d -> innerLoop (fst d) (snd d))
The above fragment is employing two temporary arrays, which is wasteful. You can eliminate these extra arrays by using computation expression only:
[| for i in 0 .. (Array.length secondPart)-1 do
let first, second = SliceAtMarkerElement i
yield! innerLoop first second (* concatenating results *)
|]
UPDATE:
As clarified in the comment, you want to return an array of arrays where each array is a permutation. So your change would work and map operations should be:
[| for i in 0 .. (Array.length secondPart)-1 do
let first, second = SliceAtMarkerElement i
yield innerLoop first second (* returning each array as a permutation *)
|]