witchcrafters / witchcraft

Monads and other dark magic for Elixir
https://witchcrafters.github.io
MIT License
1.2k stars 58 forks source link

Functor.map behaviour on tuples #95

Open florius0 opened 2 years ago

florius0 commented 2 years ago

When called with first argument being tuple, Functor.map/2 applies a function only to the last element of tuple:

iex(1)> use Witchcraft
iex(2)> map({1, 2, 3}, fn x -> x + 1 end)
{1, 2, 4}

Is this intended behaviour?

florius0 commented 2 years ago

PS Looked in Witchcraft.Functor, looks like it is intended


definst Witchcraft.Functor, for: Tuple do
  def map(tuple, fun) do
    case tuple do
      {} ->
        {}

      {first} ->
        {fun.(first)}

      {first, second} ->
        {first, fun.(second)}

      {first, second, third} ->
        {first, second, fun.(third)}

      {first, second, third, fourth} ->
        {first, second, third, fun.(fourth)}

      {first, second, third, fourth, fifth} ->
        {first, second, third, fourth, fun.(fifth)}

      big_tuple ->
        last_index = tuple_size(big_tuple) - 1

        mapped =
          big_tuple
          |> elem(last_index)
          |> fun.()

        put_elem(big_tuple, last_index, mapped)
    end
  end
end

Can somebody explain my why it is so?