I'm taking a MOOC (no credit). One of the assigned problems is to write a factorial function using a function that follows this:
(’a->’a)->(’a->bool)->’a->’a
I've created that function:
fun do_until (f, g) = fn x => case g(f x) of
false => f x
| _ => do_until(f,g) (f x);
but I've had difficulty using my do_until function to implement factorial.
The solution should follow this format I believe:
fun factorial x = (do_until (f, g)) x
The problem I see is that the 'g' function can only validate the result, and if validated, then return that result. Since the function type descriptors are fairly restrictive, it limits you from passing in a tuple to g, then verifying off part of the tuple and returning the other part. ie. (factorial, int to mult) then g would verify from #2 and return #1. Unfortunately the types prevent that. I'm starting to think using do_until as a helper function is impossible unless you compute the factorial some other way and then 'g' would just compare your result to that. Please let me know if I'm wrong and where to go next!
You have the wrong type – the function should be curried – and you will probably have more luck if you give the parameters more descriptive names than "f" and "g":
fun do_until next done x = if done x
then x
else do_until next done (next x)
Note that you can pass anything from factorial to do_until – for instance a tuple that holds your computation state – and then "take it apart" once do_until is done. (I suspect that this is why you're stuck.)
Related
My question
I'm referring to a function which does essentially the following (modulo const, &, perfect forwarding, or whatever is appropriate):
auto constexpr dollar = [](auto f, auto x){ return f(x); }; // Why calling it "dollar"? Keep reading...
Is such a function expressable only via Boost.Hana?
Why did I think of it?
In Haskell, such a function exists, and it's called ($) ($ in infix form), and its definition is the following (source code)
($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b
f $ x = f x
and you could write the second line simply as either of the following
(f $) = f
($) f = f
where the second form makes it apparent that ($) is essentially the same as the id (identity function)
id :: a -> a
id x = x
just with a signature that enforces that the first argument be of function type a -> b and the second argument of type a.
Indeed, applying f to x in Haskell can be done also by writing this
f `id` x
i.e. using `id` instead of $.¹
How is that related to Hana?
Since Hana does offer an id function, I was wondering if that (maybe together with something else) can be used to define a function application utility without manually writing the lambda at the top of this post.
The difficult part
The hard part here is that when you write f `id` x in Haskell, there's not much really a point in arguing on whether you're passing 1 or 2 arguments to id, because all functions are curried by default.
That's not true in C++. For instance I can do this:
#include <boost/hana/functional/id.hpp>
#include <iostream>
using boost::hana::id;
int main() {
auto plus1 = [](int x){ return x + 1; };
std::cout << id(plus1)(3) << std::endl; // prints 4
}
which looks a lot like id is curried and is being given two inputs one after the other rather than together, but that's not true. It's just that id(plus1) is returning plus1, which is fed with 3. I don't know how to get the following (which would be equivalent to plus1 `id` 3 or id plus1 3 in Haskell) work:
std::cout << id(plus1, 3) << std::endl; // doesn't even compile obviously
The true origin of the puzzle
After reading To Mock a Mockingbird, I wondered: "How do I implement the Thrush in C++ only with Boost.Hana?" (And the Thrush is the boost::hana::flipped version of the function application operator.)
¹In reality it's not exactly the same if want to write chains of applications, as the two operators have different associativity, so f $ g $ x == f `id` (g `id` x), but this is not relevant to the question, I believe.
I have the following function :
let extract n l =
let rec aux acc pro = function
|[] -> acc
|a::b -> if (List.length pro) = n then aux (pro::acc) [] (a::b) else aux acc (a::pro) b; aux acc (pro) b
in aux [] [] l
As you can see in my pattern matching at the second test's case I am calling two times the function. Is it possible ?
So it is possible to have this kind of function :
let rec some_function = function
| [] ->[]
| a::b -> some_function b; some_function b (*so I am calling two times the function in a single test*)
I am asking this question because here I have the following warning :
File "main.ml", line 4, characters 48-72:
Warning 10: this expression should have type unit.
So there is a problem at the exact place I called two times my recursive function.
It might be because I am using ; but in this case how could I seperate these two calls ?
Thank you !
To add onto FlorianWeimer's answer, some information about your error message.
Warning 10: this expression should have type unit.
OCaml is strongly typed. Therefore, if a function returns, say, an integer or a list, and you don't do anything with it, it'll wonder what's going on and warn you.
A function call like print_int 5; returns (), which is of type unit. That basically means that it returns nothing because you're not calling it to compute something, but to do something. It has done that thing and now it returns and you move on.
But a function call like float_of_int 5;, that returns a value (the float 5.0). You (probably) didn't call it to do something, but to compute something, and what it returns is what interests you. Same goes for arithmetic expressions like 3+6; or for straight up values like 10; or "abc"; or [];.
That's why, if you write one of these things that have a value and you don't use that value (in an assignment, or as a parameter of another function), OCaml warns you. It tells you "I computed something that I didn't assign, didn't return, and didn't use as the argument of something else. Usually, things of type unit are the only things like that. Are you sure you don't have a bug in your code?"
Sometimes you know what you're doing and you don't want that warning. In that case, you can call the ignore function. ignore will take anything and ignore it, returning (). For instance, ignore 5; or ignore (float_of_int 10); won't throw the "this expression should have type unit" warnings that you'd get with 5; or float_of_int 10;.
It is possible in the sense that the compiler accepts it, but it only makes sense if you do something with the result (or the function has a side effect). The classic example for two function calls is the recursive computation of the Fibonacci sequence:
let rec fib = function
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)
I want to convert a sequence to a list using List.init. I want at each step to retrieve the i th value of s.
let to_list s =
let n = length s in
List.init n
(fun _i ->
match s () with
| Nil -> assert false
| Cons (a, sr) -> a)
This is giving me a list initialized with the first element of s only. Is it possible in OCaml to initialize the list with all the values of s?
It may help to study the definition of List.init.
There are two variations depending on the size of the list: a tail recursive one, init_tailrec_aux, whose result is in reverse order, and a basic one, init_aux. They have identical results, so we need only look at init_aux:
let rec init_aux i n f =
if i >= n then []
else
let r = f i in
r :: init_aux (i+1) n f
This function recursively increments a counter i until it reaches a limit n. For each value of the counter that is strictly less than the limit, it adds the value given by f i to the head of the list being produced.
The question now is, what does your anonymous function do when called with different values of i?:
let f_anon =
(fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
Regardless of _i, it always gives the head of the list produced by s (), and if s () always returns the same list, then f_anon 0 = f_anon 1 = f_anon 2 = f_anon 3 = hd (s ()).
Jeffrey Scofield's answer describes a technique for giving a different value at each _i, and I agree with his suggestion that List.init is not the best solution for this problem.
The essence of the problem is that you're not saving sr, which would let you retrieve the next element of the sequence.
However, the slightly larger problem is that List.init passes only an int as an argument to the initialization function. So even if you did keep track of sr, there's no way it can be passed to your initialization function.
You can do what you want using the impure parts of OCaml. E.g., you could save sr in a global reference variable at each step and retrieve it in the next call to the initialization function. However, this is really quite a cumbersome way to produce your list.
I would suggest not using List.init. You can write a straightforward recursive function to do what you want. (If you care about tail recursion, you can write a slightly less straightforward function.)
using a recursive function will increase the complexity so i think that initializing directly the list (or array) at the corresponding length will be better but i don't really know how to get a different value at each _i like Jeffrey Scofield said i am not really familiar with ocaml especially sequences so i have some difficulties doing that:(
I try to define function with the following protocol:
[(1,2), (6,5), (9,10)] -> [3, 11, 19]
Here is what I have now:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else (#1 hd(l)) + (#2 hd(l))::sum_pairs(tl(l))
According to type checker I have some type mismatch, but I can't figure out where exactly I'm wrong.
This code runs in PolyML 5.2:
fun sum_pairs (l : (int * int) list) =
if null l
then []
else ((#1 (hd l)) + (#2 (hd l))) :: sum_pairs(tl l)
(* ------------^-------------^ *)
The difference from yours is subtle, but significant: (#1 hd(l)) is different from (#1 (hd l)); the former doesn't do what you think - it attempts to extract the first tuple field of hd, which is a function!
While we're at it, why don't we attempt to rewrite the function to make it a bit more idiomatic? For starters, we can eliminate the if expression and the clunky tuple extraction by matching on the argument in the function head, like so:
fun sum_pairs [] = []
| sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest)
We've split the function into two clauses, the first one matching the empty list (the recursive base case), and the second one matching a nonempty list. As you can see, this significantly simplified the function and, in my opinion, made it considerably easier to read.
As it turns out, applying a function to the elements of a list to generate a new list is an incredibly common pattern. The basis library provides a builtin function called map to aid us in this task:
fun sum_pairs l = map (fn (a, b) => a + b) l
Here I'm using an anonymous function to add the pairs together. But we can do even better! By exploiting currying we can simply define the function as:
val sum_pairs = map (fn (a, b) => a + b)
The function map is curried so that applying it to a function returns a new function that accepts a list - in this case, a list of integer pairs.
But wait a minute! It looks like this anonymous function is just applying the addition operator to its arguments! Indeed it is. Let's get rid of that too:
val sum_pairs = map op+
Here, op+ denotes a builtin function that applies the addition operator, much like our function literal (above) did.
Edit: Answers to the follow-up questions:
What about arguments types. It looks like you've completely eliminate argument list in the function definition (header). Is it true or I've missed something?
Usually the compiler is able to infer the types from context. For instance, given the following function:
fun add (a, b) = a + b
The compiler can easily infer the type int * int -> int, as the arguments are involved in an addition (if you want real, you have to say so).
Could you explain what is happening here sum_pairs ((a, b)::rest) = (a + b)::sum_pairs(rest). Sorry for may be dummy question, but I just want to fully understand it. Especially what = means in this context and what order of evaluation of this expression?
Here we're defining a function in two clauses. The first clause, sum_pairs [] = [], matches an empty list and returns an empty list. The second one, sum_pairs ((a, b)::rest) = ..., matches a list beginning with a pair. When you're new to functional programming, this might look like magic. But to illustrate what's going on, we could rewrite the clausal definition using case, as follows:
fun sum_pairs l =
case l of
[] => []
| ((a, b)::rest) => (a + b)::sum_pairs(rest)
The clauses will be tried in order, until one matches. If no clause matches, a Match expression is raised. For example, if you omitted the first clause, the function would always fail because l will eventually be the empty list (either it's empty from the beginning, or we've recursed all the way to the end).
As for the equals sign, it means the same thing as in any other function definition. It separates the arguments of the function from the function body. As for evaluation order, the most important observation is that sum_pairs(rest) must happen before the cons (::), so the function is not tail recursive.
I'm trying to figure out how to implement fixed point iteration in Ocaml. That is, given a function f and an x, I want to calculate what the final value of what f(f(f(x)...)) will be.
So for example, if my function is x/2 and my x=50, my answer should be 0.
So far, I have
let rec computed_fixed_point eq f x =
if (x == f x) then
x
else
computed_fixed_point eq f (f x)
This works for the function x/2 and x=50 (giving me 0), but for functions that go off to infinity or something other than 0, it doesn't seem to work.
Can another give me some advice? Thanks!
It's a little hard to understand the rationale of this problem. Not every function is going to have a fixed point. For example fun x -> (x + 1) mod 5. Not every function with a fixed point will reach the fixed point by repeated application from a distinct starting point. (I just did some googling, and fixed points like this are called "attractive fixed points".)
Here are some comments:
You shouldn't use ==, which is the physical equality operator. You possibly want to use =, equality of values.
However, I don't see what the eq parameter is for. Perhaps the caller is allowed to specify what equality to use. If so, you should use this instead of ==.