diff --git a/exercises/exercisesforhof/answers.ml b/exercises/exercisesforhof/answers.ml new file mode 100644 index 0000000..9cb6928 --- /dev/null +++ b/exercises/exercisesforhof/answers.ml @@ -0,0 +1,50 @@ + +(* 1. `filter_map` function: *) +let filter_map f l = + List.fold_right + (fun x acc -> + match f x with + | Some y -> y :: acc + | None -> acc) + l [] + +(* This function uses `fold_right` to iterate through the list `l` from right to left, and applies the function `f` to each element. If `f` returns a `Some` value, it is appended to the result list, otherwise it is skipped. *) + +(* 2. `compose` function: *) + + +let compose f g x = f (g x) + + +(* This function takes two functions `f` and `g`, and returns a new function that applies `g` to its argument, and then applies `f` to the result. *) + +(* 3. `exists` function: *) + + +let exists p l = + List.fold_left + (fun acc x -> acc || p x) + false l + + +(* This function uses `fold_left` to iterate through the list `l` from left to right, and applies the predicate function `p` to each element. If `p` returns `true` for any element, the function returns `true`, otherwise it returns `false`. *) + +(* 4. `iter2` function: *) + + +let iter2 f l1 l2 = + List.iter2 f l1 l2 + + +(* This function uses the built-in `iter2` function from the `List` module, which iterates through two lists `l1` and `l2` in parallel, applying the function `f` to the corresponding elements of each list. *) + +(* 5. `flatten` function: *) + + +let flatten l = + List.fold_left + (fun acc x -> acc @ x) + [] l + + +(* This function uses `fold_left` to iterate through the list `l` from left to right, and appends each sub-list to the accumulator list. The resulting list is flattened, with all the elements of the sub-lists combined into a single list. Note that this implementation is not very efficient, as it performs many list concatenations, which can be slow for large lists. *) \ No newline at end of file diff --git a/exercises/exercisesforhof/questions.md b/exercises/exercisesforhof/questions.md new file mode 100644 index 0000000..70c594c --- /dev/null +++ b/exercises/exercisesforhof/questions.md @@ -0,0 +1,12 @@ +Questions: +These are a few questions that you can solve using higher-order functions in OCaml: + +1. Write a function `filter_map` that takes a list `l` and a function `f` that returns an optional value, and returns a new list containing only the non-`None` values returned by `f`. + +2. Write a function `compose` that takes two functions `f` and `g` and returns a new function that applies `f` to the result of applying `g` to its argument. + +3. Write a function `exists` that takes a list `l` and a predicate function `p`, and returns `true` if there exists an element in `l` for which `p` returns `true`, and `false` otherwise. + +4. Write a function `iter2` that takes two lists `l1` and `l2` and a function `f`, and applies `f` to the corresponding elements of `l1` and `l2`. The function `f` takes two arguments, one from `l1` and one from `l2`. + +5. Write a function `flatten` that takes a list of lists `l` and returns a flattened list containing all the elements of the sub-lists. diff --git a/tutorials/basic-highorderfunctions.md b/tutorials/basic-highorderfunctions.md new file mode 100644 index 0000000..d0c1bc9 --- /dev/null +++ b/tutorials/basic-highorderfunctions.md @@ -0,0 +1,87 @@ + Higher-order functions + +----------------------------------------------------------------------------------------------------------------------------------------- + +Higher-order functions are functions that take other functions as arguments or return functions as their results. Here is an example of a higher-order function that takes a function `f` and applies it to each element of a list `l`: + + +let rec map f l = + match l with + | [] -> [] + | x :: xs -> f x :: map f xs + + +The `map` function takes a function `f` as its first argument and a list `l` as its second argument. It applies `f` to each element of `l` and returns a new list containing the results. For example, if we define a function `square` that squares its argument: + + +let square x = x * x + + +We can use `map` to apply `square` to each element of a list: + + +let l = [1; 2; 3] +let l_squared = map square l (* returns [1; 4; 9] *) + +----------------------------------------------------------------------------------------------------------------------------------------- + +Another example of a higher-order function in OCaml is the `fold_left` function, which takes a function `f`, an initial accumulator value `acc`, and a list `l`, and applies `f` to each element of `l` and the current accumulator value to produce a new accumulator value. Here's an example implementation of `fold_left`: + + +let rec fold_left f acc l = + match l with + | [] -> acc + | x :: xs -> fold_left f (f acc x) xs + + +We can use `fold_left` to compute the sum of a list of integers: + + +let sum l = fold_left (+) 0 l + + +The `sum` function takes a list `l` as its argument and uses `fold_left` with the `+` operator and an initial accumulator value of `0` to compute the sum of `l`. For example: + + +let l = [1; 2; 3] +let sum_l = sum l (* returns 6 *) + +------------------------------------------------------------------------------------------------------------------------------------------ + +`fold_right` is a higher-order function in OCaml that is similar to `fold_left`, but it processes the elements of a list from right to left instead of from left to right. + +Here's the signature of `fold_right`: + + +val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b + + +The first argument is a function `f` that takes an element of the list and an accumulator value and returns a new accumulator value. The second argument is the list to be processed, and the third argument is the initial accumulator value. + +Here's an example implementation of `fold_right`: + + +let rec fold_right f l acc = + match l with + | [] -> acc + | x :: xs -> f x (fold_right f xs acc) + + +The implementation is similar to `fold_left`, except that it calls itself recursively on the tail of the list (`xs`) and passes the current accumulator value (`acc`) as the second argument to `f`. + +Here's an example of using `fold_right` to compute the product of a list of integers: + + +let product l = fold_right (fun x acc -> x * acc) l 1 + + +The `product` function takes a list `l` as its argument and uses `fold_right` with a function that multiplies the current element by the accumulator and an initial accumulator value of `1` to compute the product of `l`. For example: + + +let l = [1; 2; 3] +let product_l = product l (* returns 6 *) + + +Note: `fold_right` is often less efficient than `fold_left` because it processes the list in reverse order. This leads to an excessive stack usage for large lists. + +_____________________________________________________________________________________________________________________________________________ \ No newline at end of file