Hello guys I am trying to make a simple recursive method that simply takes in an accumulator and a target value. Then add one to the accumulator until it reaches the target value. I am very new to Ocaml but have a decent background in java.
I wrote up a quick snippet of code that shows what I want to do in java:
public static int rec(int acc,int target) {
if (acc == target) {
return 0;
} else {
return rec(acc+1, target);
}
}
here is my attempt to mimic this code in Ocaml:
let h_sequence x =
let rec helper acc x = function
| acc -> x
| _ -> helper acc+1 x
in
helper 0 x;;
however I get the following error:
Error: This expression has type 'a -> 'b -> 'a
but an expression was expected of type int
Here is how I am trying to understand the Ocaml code. So we have a function h_sequence that has a paramater x. Inside of the function h_sequence we have a recursive function named helper which has two paramaters acc and x. If acc = x then return x. Else start the recursion by passing in helper, add one to the acc and then return x. And after the in it is passing the helper function, setting 0 for the acc and setting x as x. Please let me know if my logic is off. Any help will be much appreciated!
edit new code:
let h_sequence x =
let rec helper acc x =
if acc = x then
acc
else
helper (acc+1) x
in
helper 0 x;;
As #Flux says, your helper function has 3 parameters. You should also be aware that the pattern acc will match all values. Patterns consist essentially of constants, and any names appearing in a pattern will match (and be bound to) any corresponding value.
To compare x against acc you should just use an if statement.
Since you don't really want to use pattern matching, you can simplify things by removing function. You'll end up with something like this for the helper function:
let rec helper acc x =
if x = acc then (* One of the cases *)
else (* The other case *)
... we have a recursive function named helper which has two parameters acc and x.
You are getting the error because the recursive function helper actually has three "parameters": acc, x, and another "parameter" that that is matched using function. The error message has given you this clue ('a -> 'b -> 'a).
Let's now look at the helper function:
let rec helper acc x = function
| zzz -> x (* Equivalent to `| _ -> x` *)
| _ -> helper acc+1 x
Mistakes:
function does pattern matching. Everything will match the pattern zzz, which means that the next pattern (| _ -> helper acc+1 x) is useless because it will never be matched. Note that I've changed the pattern's name from your acc to zzz in order to emphasize that function actually matching patterns.
helper acc+1 x is equivalent to (helper acc) + 1 x, which is not what you want. It should be helper (acc+1) x instead.
Solution
let rec helper acc x =
if acc >= x then 0
else helper (acc+1) x
You should use >= instead of = to handle the case where x is negative.
Related
I need to write a function that takes a list of strings and finds the largest string in the list. In case of tie, it should return string closest to the end of the list. The catch is it needs to iterate through the list using List.foldl and cannot use recursive calls except for those in the library function of List,foldl.
The following code works fine.
fun longest_string2 str_list =
List.foldl(fn (x, acc) => if String.size x >= String.size acc then x else acc) "” str_list
If I run longest_string2 ["Apple", "ball", "Bpple”]; in REPL, I get val it = "Bpple" : string
However, if I reverse the arguments of anonymous function as below I get val it = "Apple" : string.
Since the anonymous function is accessing the elements by name and not position, why does this makes difference?
The definition of List.foldl is
fun foldl (f: 'a*'b->'b) (acc: 'b) (l: 'a list): 'b =
case l of
[] => acc
| x::xs => foldl f (f(x,acc)) xs
If you reverse arguments of the anonymous function, your function becomes the following: (correct me if I misinterpreted your question)
fun longest_string2 str_list =
List.foldl(fn (acc, x) => if String.size x >= String.size acc then x else acc) "” str_list
If your pass ["Apple", "ball", "Bpple”] as argument to longest_string2 now, the foldl function will pattern match your list with x::xs, where x is “Apple” and xs is ["ball", "Bpple”]. When you compute the updated accumulator using f(x, acc), x and acc gets swapped. In other words, in your anonymous function (with reversed arguments), you would be assuming that the first argument would be ”” and the second argument would be Apple but the implementation of List.foldl will pass f(“Apple”, “”). In this case, your anonymous function will label “Apple” as “acc” and “” as “x”.
#3123 has most answered the question, but has not directly addressed this statement in the question.
Since the anonymous function is accessing the elements by name and not
position, why does this makes difference?
foldl takes a function which takes a tuple as its argument, which is positional.
We could define a fold function which takes a record as its argument instead if we really wanted to achieve this:
fun namedFold _ acc [] = acc
| namedFold f acc (x::xs) =
namedFold f (f {acc=acc, x=x}) xs;
And then call it as:
namedFold (fn { acc, x } => acc + x) 0 [1,2,3,4]
Or as:
namedFold (fn { x, acc } => acc + x) 0 [1,2,3,4]
And get the same result.
But then the type of namedFold is fn :({acc: 'a, x: 'b} -> 'a) -> 'a -> 'b list -> 'a and it becomes essentially impossible to easily pass existing functions to it. With foldl defined the way it is, we can easily rewrite that previous called to namedFold as:
foldl op+ 0 [1,2,3,4]
Because op+ has the same signature as the first argument to foldl.
let list_min_fold = List.fold (fun acc -> List.min acc ) 0 lst
printfn"Using regular List.fold function:\n The minimum is: %A\n"
(list_min_fold)
When I execute my code this error displays:
error FS0001: The type '('a -> 'b)' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface
Why? Please help :(
Are you trying to find the smallest number in a list? If so, you need to use the min function (which takes just two arguments) rather than List.min (which takes a list of arguments):
To keep the code the most similar to your example, you can write (note also that starting with 0 is not going to work, so I used System.Int32.MaxValue instead):
let lst = [4;3;1;2;5;]
let list_min_fold = List.fold (fun acc -> min acc) System.Int32.MaxValue lst
It is also worth noting that the function you pass to fold takes two arguments - the state acc and the current value:
let list_min_fold = List.fold (fun acc v -> min acc v) System.Int32.MaxValue lst
But thanks to partial function application you can omit one of them (as you did), or both of them:
let list_min_fold = List.fold min System.Int32.MaxValue lst
as always Tomas answer is spot on so I have but a small remark:
as you probably saw it makes no sense to try to find the minimum of an empty list (so the function probably should be of type 'a option and when you have an non-empty list it's very easy to use List.reduce (which is basically just a fold for binary operations and min is a great candidate for such an operation):
let list_min xs =
match xs with
| [] -> None
| _ -> List.reduce min xs
|> Some
this way you get:
> list_min [2;1;5;3];;
val it : int option = Some 1
> list_min [2;1;5;3;0];;
val it : int option = Some 0
> list_min ([] : int list);;
val it : int option = None
ok it's a fair point that the question was about fold - so if it has to be exactly List.fold you can of course do (as TheInnerLight remarked):
let list_min xs =
match xs with
| [] -> None
| (x::xs) -> List.fold min x xs
|> Some
This question uses the following "lazy list" (aka "stream") type:
type 'a lazylist = Cons of 'a * (unit -> 'a lazylist)
My question is: how to define a tail-recursive function lcycle that takes a non-empty (and non-lazy) list l as argument, and returns the lazylist corresponding to repeatedly cycling over the elements l. For example:
# ltake (lcycle [1; 2; 3]) 10;;
- : int list = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1]
(ltake is a lazy analogue of List::take; I give one implementation at the end of this post.)
I have implemented several non-tail-recursive versions of lcycles, such as:
let lcycle l =
let rec inner l' =
match l' with
| [] -> raise (Invalid_argument "lcycle: empty list")
| [h] -> Cons (h, fun () -> inner l)
| h::t -> Cons (h, fun () -> inner t)
in inner l
...but I have not managed to write a tail-recursive one.
Basically, I'm running into the problem that lazy evaluation is implemented by constructs of the form
Cons (a, fun () -> <lazylist>)
This means that all my recursive calls happen within such a construct, which is incompatible with tail recursion.
Assuming the lazylist type as defined above, is it possible to define a tail-recursive lcycle? Or is this inherently impossible with OCaml?
EDIT: My motivation here is not to "fix" my implementation of lcycle by making it tail-recursive, but rather to find out whether it is even possible to implement a tail recursive version of lcycle, given the definition of lazylist above. Therefore, pointing out that my lcycle is fine misses what I'm trying to get at. I'm sorry I did not make this point sufficiently clear in my original post.
This implementation of ltake, as well as the definition of the lazylist type above, comes from here:
let rec ltake (Cons (h, tf)) n =
match n with
0 -> []
| _ -> h :: ltake (tf ()) (n - 1)
I don't see much of a problem with this definition. The call to inner is within a function which won't be invoked until lcycle has returned. Thus there is no stack safety issue.
Here's an alternative which moves the empty list test out of the lazy loop:
let lcycle = function
| [] -> invalid_arg "lcycle: empty"
| x::xs ->
let rec first = Cons (x, fun () -> inner xs)
and inner = function
| [] -> first
| y::ys -> Cons (y, fun () -> inner ys) in
first
The problem is that you're trying to solve a problem that doesn't exist. of_list function will not take any stack space, and this is why lazy lists are so great. Let me try to explain the process. When you apply of_list function to a non empty list, it creates a Cons of the head of the list and a closure, that captures a reference to the tail of the list. Afterwards it momentary returns. Nothing more. So it takes only few words of memory, and none of them uses stack. One word contains x value, another contains a closure, that captures only a pointer to the xs.
So then, you deconstruct this pair, you got the value x that you can use right now, and function next, that is indeed the closure that, when invoked, will be applied to a list and if it is nonempty, will return another Cons. Note, that previous cons will be already destroyed to junk, so new memory won't be used.
If you do not believe, you can construct an of_list function that will never terminate (i.e., will cycle over the list), and print it with a iter function. It will run for ever, without taking any memory.
type 'a lazylist = Cons of 'a * (unit -> 'a lazylist)
let of_list lst =
let rec loop = function
| [] -> loop lst
| x :: xs -> Cons (x, fun () -> loop xs) in
loop lst
let rec iter (Cons (a, next)) f =
f a;
iter (next ()) f
I have this function that takes a list of lists of strings and a string and then return a list of all the elements in each list that contains the string passed but without the string passed.
myfilter([["a","b"],["c","d"],["e","a","x"]], "a") -> ["b","e","x"]
fun myfilter(list : string list list, s : string) =
case list of
[] => []
|xs::xs' => case all_except_option(s, xs) of (* helper function that does it for a string and a list of strings *)
NONE => []
|SOME n => if n = xs
then myfilter(xs',s)
else n#myfilter(xs',s)
Now this is as you can see is a recursive function and I want to convert it to a tail recursive function. I am familiar with the examples of tail recursion but I am failing to see how I can do it in the function above
When you think tail recursive, the next thing you think should be "accumulator".
The reason a function is not tail recursive is that it has to call itself to obtain some result, and then do something with that result. If we can move that calculation into the recursive call, then it's tail recursive.
In this case, the calculation you're making is that you're putting two lists together. So the solution would be a function declared inside a let ... in ... end, that takes a third parameter - an accumulator. Then you can add items to the accumulator as you go.
A good example is a tail-recursive factorial function. Here's the normal factorial function:
fun fact 0 = 1
| fact x = x * fact (x-1)
To make it tail-recursive, we define a local function which takes an accumulator, and do the multiplication there.
fun fact x =
let
fun fact' 0 acc = acc
| fact' x acc = fact (x-1) (x*acc)
in
fact' x 1
end
We use 1 as the starting value for the accumulator, because multiplying with 1 has no effect.
Okay, so other than that, there is a little thing you can do to improve your code. I've noticed a lot of people here that do this:
fun foo xs =
case xs of
[] => ...
| (x::xs) => ...
Where it would be much nicer to just do:
fun foo [] = ...
| foo (x::xs) = ...
I'm trying to write a simple recursive function that look over list and return a pair of integer. This is easy to write in c/c++/java but i'm new to ocaml so somehow hard to find out the solution due to type conflict
it should goes like ..
let rec test p l = ... ;;
val separate : (’a -> bool) -> ’a list -> int * int = <fun>
test (fun x -> x mod 2 = 0) [-3; 5; 2; -6];;
- : int * int = (2, 2)
so the problem is how can i recursively return value on tuple ..
One problem here is that you are returning two different types: an int for an empty list, or a tuple otherwise. It needs to be one or the other.
Another problem is that you are trying to add 1 to test, but test is a function, not a value. You need to call test on something else for it to return a value, but even then it is supposed to return a tuple, which you can't add to an integer.
I can't figure out what you want the code to do, but if you update your question with that info I can help more.
One guess that I have is that you want to count the positive numbers in the list, in which case you could write it like this:
let rec test l =
match l with [] -> 0
| x::xs -> if x > 0 then 1 + (test xs)
else test xs;;
Update: since you've edited to clarify the problem, modify the above code as follows:
let test l =
let rec test_helper l pos nonpos =
match l with [] -> (pos, nonpos)
| x::xs -> if x > 0 then test_helper xs 1+pos, nonpos
else test_helper xs pos 1+nonpos
in test_helper l 0 0;;
Using the accumulators help a lot in this case. It also makes the function tail-recursive which is always good practice.
Been away from OCaml for a bit, but I think this will do the trick in regards to REALFREE's description in the comment
let rec test l =
match l with
[] -> (0,0)
| x::xs ->
if x > 0 then match (test xs) with (x,y) -> (x+1, y)
else match (test xs) with (x,y) -> (x, y+1);;
You can used the nested match statements to pull out pieces of the tuple to modify
EDIT:
I didn't know about the syntax Pascal Cuoq mentioned in his comment below, here's the code like that, it's neater and a little shorter:
let rec test l =
match l with
[] -> (0,0)
| x::xs ->
if x > 0 then let (x,y) = test xs in (x+1, y)
else let (x,y) = test xs in (x, y+1);;
But the accepted answer is still much better, especially with the tail recursion ;).