Clarification on `Algae.Free` usage
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!
Thank you for submitting an issue! It means a lot that you took the time -- it helps us be better 🙏