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
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 beThere 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:
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 oneThanks in advance for your help!