src/automata.erl

-module(automata).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/automata.gleam").
-export([new/3, initial_state/1, step/3, run/2, accepts/2]).
-export_type([automaton/2]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

-opaque automaton(DKT, DKU) :: {automaton,
        DKT,
        fun((DKT, DKU) -> DKT),
        fun((DKT) -> boolean())}.

-file("src/automata.gleam", 16).
?DOC(
    " Construct an automaton from its initial state, transition\n"
    " function, and acceptance predicate.\n"
).
-spec new(DKV, fun((DKV, DKW) -> DKV), fun((DKV) -> boolean())) -> automaton(DKV, DKW).
new(Initial_state, Transition, Accepting) ->
    {automaton, Initial_state, Transition, Accepting}.

-file("src/automata.gleam", 29).
?DOC(" Return the initial state.\n").
-spec initial_state(automaton(DKZ, any())) -> DKZ.
initial_state(Automaton) ->
    erlang:element(2, Automaton).

-file("src/automata.gleam", 35).
?DOC(
    " Apply one transition from the supplied state using one input\n"
    " symbol.\n"
).
-spec step(automaton(DLD, DLE), DLD, DLE) -> DLD.
step(Automaton, State, Symbol) ->
    (erlang:element(3, Automaton))(State, Symbol).

-file("src/automata.gleam", 45).
?DOC(
    " Fold a list of input symbols over the automaton's transition\n"
    " function and return the resulting state.\n"
).
-spec run(automaton(DLH, DLI), list(DLI)) -> DLH.
run(Automaton, Inputs) ->
    gleam@list:fold(
        Inputs,
        erlang:element(2, Automaton),
        fun(State, Symbol) -> (erlang:element(3, Automaton))(State, Symbol) end
    ).

-file("src/automata.gleam", 52).
?DOC(" Return True when the automaton accepts the supplied input.\n").
-spec accepts(automaton(any(), DLN), list(DLN)) -> boolean().
accepts(Automaton, Inputs) ->
    (erlang:element(4, Automaton))(run(Automaton, Inputs)).