defmodule Maps do
def map([],[]) do [] end
def map([x|xs], [x1 | xs1])
do map([xs],[xs1]) ++ [(x + x1) | []] end
end
I don't get what's wrong with it. Suppose you run Maps.map([1],[2]). It should then do map(xs,xs1) and since xs = [] and xs1 = [] is empty, map ([],[]) should return [], which ends the recursion. Then
[] ++ [1+2] = [3] so the result should return [3]. However, this just freezes my terminal.
xs and xs1 are already lists in the second clause, but you're wrapping it in another list, which is creating infinite recursion. Changing:
map([xs],[xs1]) ++ [(x + x1) | []]
to:
map(xs, xs1) ++ [(x + x1) | []]
Gives the expected output:
iex(1)> Maps.map([1, 2, 3], [4, 5, 6])
[9, 7, 5]
Sidenote: [x | []] is the same as [x], so you could rewrite that to just:
map(xs, xs1) ++ [x + x1]
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])
Hello I am new to Sml/nj, and I am trying to modify an input to give it to a function. I'm stuck at modifying the input.
Specifically, I read the input and store it in a list. I want to make a function that given an even length list, it will make a new list, but with 2-element tuples.
For example, if my input is the list [2, 7, 4, 6, 5, 8] I want to create this list [(2, 7), (4, 6), (5, 8)]
I tried this but unfortunately it doesn't work:
fun maketuples [] = []
| maketuples x::xs = (x, hd xs) # makektuples (tl xs)
There's a couple things here:
If you're pattern matching on a constructor as a function argument, you need to put parentheses around it for it to be parsed the way you'd like, i.e., x::xs -> (x::xs)
You have a typo in the second clause (makektuples; extra k)
You're using append (#) on a int * int and a (int * int) list. The domain of this function is in fact, 'a list * 'a list, i.e., both of its arguments must be lists of the same type.
We could revise this like so:
fun maketuples [] = []
| maketuples (x::xs) = [(x, hd xs)] # maketuples (tl xs)
But singleton append isn't really something you should do. Why? It's cleaner to just use cons:
fun maketuples [] = []
| maketuples (x::xs) = (x, hd xs) :: maketuples (tl xs)
We can clean this up some more by removing the calls to hd and tl by just destructing further in the function arguments
fun maketuples [] = []
| maketuples (x::y::xs) = (x, y) :: maketuples xs
and you could perhaps handle an error better (one possibility being with exceptions):
fun maketuples [] = []
| maketuples (x::y::xs) = (x, y) :: maketuples xs
| maketuples _ = raise Fail "Not an even length list"
I am trying to get first and last element of the list in OCaml. I expect that my function will be like
'a list -> 'a * 'a
What I am trying to do is
let lista = [1;2;3;4;6;0];;
let rec first_last myList =
match myList with
[x] -> (List.hd lista,x)
| head::tail ->
first_last tail;;
first_last lista;;
Of course because of I made list as integer then I am doing this syntax like
*int list -> int * 'a
The point is that I dont have idea how to do this function for 'a.
Whats the direction?
The direction is to write two different functions first and last and implement the first_and_last function as:
let first_and_last xs = first xs, last xs
Another possibility with only one function:
let rec first_last = function
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You may prefer it like that:
let rec first_last myList = match myList with
| [] -> failwith "too bad"
| [e] -> failwith "too bad"
| [e1;e2] -> (e1,e2)
| e1 :: _ :: r -> first_last (e1::r)
You can create two separate functions to return first element and last element, and then in your first_and_last function return a tuple (first_element, last_element).
let rec first_element list =
match list with
| [] -> failwith "List is empty"
| first_el::rest_of_list -> first_el
let rec last_element list =
match list with
| [] -> failwith "List is empty"
| [x] -> x
| first_el::rest_of_list -> last_element rest_of_list
You can create a helper function that has a base-case of the empty-list - for which it returns itself, and otherwise checks if the next recursive call will return an empty list. If it does, return the current element (which is by definition the last element in the list), and if it doesn't, return what was returned by the recursive call.
For the regular (non-helper) method, if the list is at least one element long (i.e. hd::tl = hd::[]) then you can just concatenate the list you got from the last function onto the head from ls.
It can be implemented as follow:
let rec last ls =
match ls with
| [] -> []
| hd::tl -> let next = last tl in
if next = [] then [hd]
else next
;;
let first_last ls =
match ls with
| [] -> failwith "Oh no!!!!! Empty list!"
| hd::tl -> hd::last tl
;;
Yet another take on this problem.
let first_last xs =
let rec last_non_empty = function
| [x] -> x
| _ :: xs' -> last_non_empty xs'
| [] -> failwith "first_last: impossible case!"
in
match xs with
| [] -> failwith "first_last"
| x::_ -> (x, last_non_empty xs)
Some properties of this implementation:
(1) it meets the specification 'a list -> 'a * 'a:
utop > #typeof "first_last";;
val first_last : 'a list -> 'a * 'a
(2) it works for singleton lists: first_last [x] = (x,x):
utop> first_last [1];;
- : int * int = (1, 1) utop> first_last ["str"];;
- : bytes * bytes = ("str", "str")
(3) it's tail-recursive (hence it won't cause stack overflow for sufficiently big lists):
utop > first_last (Array.to_list (Array.init 1000000 (fun x -> x+1)));;
- : int * int = (1, 1000000)
(4) it traverses the input list one time only; (5) it avoids creating new lists as it goes down the recursive ladder; (6) it avoids polluting the namespace (with the price of not allowing the reuse of a function like last).
And another rather simple variant, from the first principles (I was trying to illustrate "wishful thinking" in the spirit of the SICP book):
(* Not tail-recursive, might result in stack overflow *)
let rec first_last = function
| [] -> failwith "first_last"
| [x] -> (x,x)
| x :: xs -> (x, snd (first_last xs))
You could write it like this:
let first_last = function
| [] -> assert false
| x :: xs -> (x, List.fold_left (fun _ y -> y) x xs)
Or, if you are using the Base library, you could write in this way:
let first_last xs = (List.hd_exn xs, List.reduce_exn ~f:(fun _ y -> y) xs)
The basic idea is that List.fold_left (fun _ y -> y) x xs will compute the last element of x :: xs. You can prove this by induction on xs: if xs = [] then List.fold_left (fun _ y -> y) x [] = x, which is the last element of x :: []; moreover, if xs = x' :: xs' then List.fold_left (fun _ y -> y) x (x' :: xs') can be rewritten as List.fold_left (fun _ y -> y) x' xs', because List.fold_left f acc (x :: xs) = List.fold_left (f acc x) xs, hence we are finished, because this is the last element of x' :: xs' by our induction hypothesis.
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 ...
I want to find the Powerset
powerset [1;2;3] = = [[]; [3]; [2]; [2; 3]; [1]; [1; 3]; [1; 2]; [1;
2; 3]]
let rec powerset = function
| [] -> []
| x::xs -> List.map (fun ys -> xs) xs::powerset (xs)
I am having trouble with the code, this is what my output looks like now.
val it : int list list list = [[[2; 3]; [2; 3]]; [[3]]; []]
Others already pointed out to a link that uses sequence expressions and enumerates the sets lazily. That's how I would solve the problem (note that there is nothing impure or non-functional about using for inside sequence comprehension - it is just a way to generate sequence of results):
let rec powerset s = seq {
match s with
| [] -> yield []
| h::t -> for x in powerset t do yield! [x; h::x] }
That said, this can be easily translated to code that returns a list and uses higher-order functions:
let rec powerset =
function
| [] -> [[]]
| x::xs -> List.collect (fun subset -> [subset; x::subset]) (powerset xs)
The power set of an empty set is a set with single element [] (note that this is wrong in your snippet). To generate a powerset of x::xs, we first generate powerset of xs and then return two sets for every single element of the generated powerset - one is the sub set and the other is the subset with added x element. (This is done using List.collect which is like calling List.map followed by List.concat.)