algae icon indicating copy to clipboard operation
algae copied to clipboard

Clarification on `Algae.Free` usage

Open florius0 opened this issue 4 years ago • 1 comments

Im not sure if issues is a correct place to request help, however I'm trying to understand Algae.Free and it isn't as easy as it might be

There is link to an article on free monads in docs

I tried to implement Haskell code in Elixir, and here's what I've got:

import Algae
import TypeClass
use Witchcraft

defmodule Toy do
  defsum do
    defdata Output do
      output :: any()
      next :: any()
    end

    defdata Bell do
      next :: any()
    end

    defdata(Done :: none())
  end


  defimpl TypeClass.Property.Generator, for: Toy.Output do
    def generate(_) do
      [1, 1.1, "", :a]
      |> Enum.random()
      |> Toy.Output.new()
    end
  end

  defimpl TypeClass.Property.Generator, for: Toy.Bell do
    def generate(_) do
      [1, 1.1, "", :a]
      |> Enum.random()
      |> Toy.Bell.new()
    end
  end

  defimpl TypeClass.Property.Generator, for: Toy.Done do
    def generate(_), do: Toy.Done.new()
  end

  definst Witchcraft.Functor, for: Toy.Output do
    def map(%{output: output, next: next}, fun), do: %Toy.Output{output: output, next: fun.(next)}
  end

  definst Witchcraft.Functor, for: Toy.Bell do
    def map(%{next: next}, fun), do: %Toy.Bell{next: fun.(next)}
  end

  definst Witchcraft.Functor, for: Toy.Done do
    def map(_, _), do: %Toy.Done{}
  end

  def of4(_, x) do
    Algae.Free.new(x ~> (&Algae.Free.Pure.new/1))
  end

  def output(x), do: fn y -> Algae.Free.new(Toy.Output.new(x, Algae.Free.Pure.new(y))) end

  def bell, do: fn y -> Algae.Free.new(Toy.Bell.new(Algae.Free.Pure.new(y))) end

  def done, do: Algae.Free.new(Toy.Done.new())

  def program do
    monad Algae.Free.new() do
      output(1)
      bell()
    end
  end
end

And here is the confusing moment Toy.program.(nil) returns %Algae.Free.Pure{pure: %Toy.Bell{next: %Algae.Free.Pure{pure: nil}}} instead of %Toy.Output{next: %Algae.Free.Pure{pure: %Toy.Bell{next: %Algae.Free.Pure{pure: nil}}}, output: 1}. It basically does not 'concatenate' previous value with the next one

Thanks in advance for your help!

florius0 avatar Jan 25 '22 01:01 florius0

Thank you for submitting an issue! It means a lot that you took the time -- it helps us be better 🙏

github-actions[bot] avatar Jan 25 '22 01:01 github-actions[bot]