FreeAst v0.3.2 FreeAst View Source
Implements something similar to Free Monad.
Usage
FreeAst.p/1
macro returns a program that can be interpreted later.
Expressions to interpret are specified with effect/2
and eval/1
calls. The first one is used to specify a desired effect, while the
second one -- to evaluate another program.
Here we define two functions that return programs with effects:
defmodule FreeAstExample.Reader do
@moduledoc false
require FreeAst
def read_line do
FreeAst.p do
effect IO, read_line()
end
end
end
defmodule FreeAstExample.Greater do
@moduledoc false
require FreeAst
alias FreeAstExample.Reader
def great do
FreeAst.p do
greating = effect Environment, greating()
greating <> ", " <> eval Reader.read_line()
end
end
end
Now we can define interpreters for these:
defmodule FreeAstExample.IOInterpreter do
@moduledoc false
def interpret(IO, :read_line, []), do: "John"
end
defmodule FreeAstExample.EnvironmentInterpreter do
@moduledoc false
def interpret(Environment, :greating, []), do: "Hi"
end
For our first program we can use the first interpreter, but for the second one we need both, so we compose interpreters:
defmodule FreeAstExample.MainInterpreter do
@moduledoc false
alias FreeAst.Interpreter
alias FreeAstExample.{IOInterpreter, EnvironmentInterpreter}
def interpreter do
Interpreter.noop()
|> Interpreter.compose(IO, &IOInterpreter.interpret/3)
|> Interpreter.compose(Environment, &EnvironmentInterpreter.interpret/3)
end
end
So now we can execute it with FreeAst.interpret/2
:
iex(1)> alias FreeAstExample.{Greater, MainInterpreter}
iex(2)> FreeAst.interpret(Greater.great(), MainInterpreter.interpreter())
"Hi, John"
Link to this section Summary
Types
Interpreter is a function that takes three arguments: action kind which is an atom or an alias, action name which is an atom, and a list of arguments of the action.
Functions
Short syntax for defining functions that return programs
Interprets a program with the supplied interpreter.
Creates a program from the supplied code block.
Link to this section Types
Interpreter is a function that takes three arguments: action kind which is an atom or an alias, action name which is an atom, and a list of arguments of the action.
Represents a program (returned by p/1
macro).
Link to this section Functions
Short syntax for defining functions that return programs
defmodule FreeAstExample.DefastExample do
@moduledoc false
import FreeAst, only: [defast: 2]
require FreeAst
defast program_v1 do
:value
end
def program_v2 do
FreeAst.p do
:value
end
end
end
iex(1)> import FreeAstExample.DefastExample
iex(2)> import FreeAst.Interpreter, only: [noop: 0]
iex(3)> result_v1 = FreeAst.interpret(program_v1(), noop())
iex(4)> result_v2 = FreeAst.interpret(program_v2(), noop())
iex(5)> result_v1 == result_v2
true
interpret(program, interpreter)
View Sourceinterpret(program(), interpreter()) :: term()
Interprets a program with the supplied interpreter.
Creates a program from the supplied code block.
iex(1)> program =
...(1)> FreeAst.p do
...(1)> x = effect IO, read_line()
...(1)> "Hi, " <> x
...(1)> end
iex(2)> FreeAst.interpret(program, fn IO, :read_line, [] -> "Kek" end)
"Hi, Kek"