Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Exercises

1.3_exercises.livemd

Exercises

Mix.install([])

Exercise 1.41

> Define a procedure double that takes a procedure of one argument as argument and returns a procedure that applies the original procedure twice.

Let’s first achieve this with a lambda. I will then solve this using modules, one with a Linear Recursive Process and another with a Linear Iterative Process.

inc = fn x ->
  x + 1
end

double = fn f ->
  fn x ->
    x
    |> f.()
    |> f.()
  end
end

IO.puts(double.(inc).(5))
IO.puts(double.(double.(double)).(inc).(5))
defmodule LinearRecursiveDouble do
  def double(fun) do
    fn x -> apply_n_times(fun, 2, x) end
  end

  defp apply_n_times(_fun, 0, x) do
    x
  end

  defp apply_n_times(fun, n, x) do
    fun.(apply_n_times(fun, n - 1, x))
  end
end

defmodule LinearIterativeDouble do
  def double(fun) do
    fn x -> apply_n_times(fun, 2, x) end
  end

  defp apply_n_times(_fun, 0, x) do
    x
  end

  defp apply_n_times(fun, n, x) do
    apply_n_times(fun, n - 1, fun.(x))
  end
end

IO.puts(LinearRecursiveDouble.double(inc).(5))
IO.puts(LinearIterativeDouble.double(inc).(5))

Exercise 1.42

> Let $f$ and $g$ be two one-argument functions. The composition $f$ after $g$ is defined to be the function ${x\mapsto f(g(x))}$. Define a procedure compose that implements composition.

square = fn x -> x * x end

compose = fn f1, f2 ->
  fn x ->
    # f1.(f2.(x))
    x
    |> f2.()
    |> f1.()
  end
end

IO.puts(compose.(square, inc).(6))

Exercise 1.43

> If $f$ is a numerical function and $n$ is a positive integer, then we can form the $n^{\text{th}}$ repeated application of $f$, which is defined to be the function whose value at $x$ is ${f(f(\dots(f(x))\dots))}$. For example, if $f$ is the function ${x\mapsto x+1}$, then the $n^{\text{th}}$ repeated application of f is the function ${x\mapsto x+n}$. Write a procedure that takes as inputs a procedure that computes $f$ and a positive integer $n$ and returns the procedure that computes the $n^{\text{th}}$ repeated application of f.

Let’s first solve this using linear recursive/iterative processes as I did above, but then add another variant that uses the compose logic.

defmodule LinearRecursiveRepeat do
  def repeat(fun, n) do
    fn x ->
      apply_n_times(fun, n, x)
    end
  end

  def apply_n_times(_fun, 0, x) do
    x
  end

  def apply_n_times(fun, n, x) do
    fun.(apply_n_times(fun, n - 1, x))
  end
end

defmodule LinearIterativeRepeat do
  def repeat(fun, n) do
    fn x ->
      apply_n_times(fun, n, x)
    end
  end

  def apply_n_times(_fun, 0, x) do
    x
  end

  def apply_n_times(fun, n, x) do
    apply_n_times(fun, n - 1, fun.(x))
  end
end

defmodule ComposedRepetition do
  def compose(f1, f2) do
    fn x ->
      x
      |> f2.()
      |> f1.()
    end
  end

  def repeat(f, n) when n > 0 do
    Enum.reduce(1..n, fn x -> x end, fn _, acc -> compose(acc, f) end)
  end
end

IO.puts(LinearRecursiveRepeat.repeat(inc, 5).(5))
IO.puts(LinearIterativeRepeat.repeat(inc, 5).(5))
IO.puts(ComposedRepetition.repeat(inc, 5).(5))