Powered by AppSignal & Oban Pro

Playing with Functors

articles/playing_with_functors.livemd

Playing with Functors

Setup

Mix.install([
  {:witchcraft, "~> 1.0"},
  {:algae, "~> 1.2"}
])
use Witchcraft
alias Algae.Either.{Right, Left}
graph TD
  Functor -.-> Traversable
  Functor -.-> Apply
  Functor -.-> Bitfunctor
  Apply -.-> Applicative
  Apply -.-> Chain
  Applicative -.-> Monad
  Chain -.-> Monad

Functor

%Right{right: 100}
~> fn y -> y * 2 end
%Right{right: [100, 200, 300]}
~> (&List.first/1)
%Right{right: [100, 200, 300]}
|> map(&List.first/1)
%Right{right: [100, 200, 300]}
|> map(&Enum.map(&1, fn x -> x + 1 end))

Apply

%Right{right: 10} ~>> %Right{right: fn x -> x * 2 end}
%Right{right: 10} |> convey(%Right{right: fn x -> x * 2 end})

lift vs map

%Right{right: 1000}
|> lift(fn x, y, z -> x + y + z end)
~> fn x -> x.(1) end
~> fn x -> x.(1) end
[10, 20, 30]
|> lift(fn x, y, z -> x + y + z end)
|> Enum.map(fn x -> x.(1) end)
|> Enum.map(fn x -> x.(1) end)
%Right{right: 1000}
|> map(fn x, y -> x + y end)

Traverse

%Right{right: [100, 200, 300]}
|> traverse(fn x -> [x] end)
%Right{right: [100, 200, 300]}
|> traverse(fn x -> x end)
|> map(fn x ->
  x ~> fn y -> y + 1 end
end)
[%Right{right: 100}, %Right{right: 200}, %Right{right: 300}]
|> traverse(fn x -> x end)
~> (&List.first/1)
[%Right{right: 100}, %Right{right: 200}, %Right{right: 300}]
|> traverse(fn x -> x end) >>>
  fn x -> Enum.map(x, fn x -> x * 2 end) end