Skip to content

Clarification on Algae.Free usage #72

@florius0

Description

@florius0

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions