Created
December 19, 2013 13:30
-
-
Save sgraf812/8039107 to your computer and use it in GitHub Desktop.
MealyMachine using functionaljava for function interfaces and tuples.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This won't really compile and is a rather ungeneralized example only to get you familiar with the syntax. | |
MealyMachine<State, Element, Option<Translation>> parser = MealyMachine.fromTransitions( | |
State.BEFORE, | |
when(State.BEFORE).then(lookOutForSourceLangHeader(source)), | |
when(State.IN_SECTION).then(lookOutForDirectHitsHeader), | |
when(State.IN_DIRECT_HITS).then(parseDirectHits(source)), | |
when(State.FINISHED).then(doNothing) | |
); | |
private enum State { | |
BEFORE, | |
IN_SECTION, | |
IN_DIRECT_HITS, | |
FINISHED | |
} | |
// Please forgive this crappy example and focus on syntax and usage. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package core.services; | |
import fj.F; | |
import fj.P2; | |
import java.util.HashMap; | |
import java.util.Map; | |
/** | |
* Models a finite state machine after the mealy model. | |
*/ | |
public class MealyMachine<TState extends Enum<TState>, TInput, TOutput> { | |
private final Map<TState, F<TInput, P2<TState, TOutput>>> handlers; | |
private TState state; | |
public MealyMachine(TState initial, Map<TState, F<TInput, P2<TState, TOutput>>> handlers) { | |
this.state = initial; | |
this.handlers = handlers; | |
} | |
public TState getState() { | |
return state; | |
} | |
public boolean isTotal() { | |
for (TState s : state.getDeclaringClass().getEnumConstants()) { | |
if (!handlers.containsKey(s)) { | |
return false; | |
} | |
} | |
return true; | |
} | |
public TOutput step(TInput input) { | |
P2<TState, TOutput> output = handlers.get(state).f(input); | |
state = output._1(); | |
return output._2(); | |
} | |
@SafeVarargs | |
public static <TState extends Enum<TState>, TInput, TOutput> | |
MealyMachine<TState, TInput, TOutput> fromTransitions(TState initial, Transition<TState, TInput, TOutput>... transitions) { | |
Map<TState, F<TInput, P2<TState, TOutput>>> handlers = new HashMap<>(transitions.length); | |
for (Transition<TState, TInput, TOutput> t : transitions) { | |
handlers.put(t.getState(), t.getHandler()); | |
} | |
return new MealyMachine<>(initial, handlers); | |
} | |
public static <TState extends Enum<TState>> TransitionBuilder<TState> when(TState state) { | |
return new TransitionBuilder<>(state); | |
} | |
public static class TransitionBuilder<TState extends Enum<TState>> { | |
private final TState state; | |
public TransitionBuilder(TState state) { | |
this.state = state; | |
} | |
public <TInput, TOutput> Transition<TState, TInput, TOutput> then(F<TInput, P2<TState, TOutput>> handler) { | |
return new Transition<>(state, handler); | |
} | |
} | |
public static class Transition<TState, TInput, TOutput> { | |
private final TState state; | |
private final F<TInput, P2<TState, TOutput>> handler; | |
public Transition(TState state, F<TInput, P2<TState, TOutput>> handler) { | |
this.state = state; | |
this.handler = handler; | |
} | |
public TState getState() { | |
return state; | |
} | |
public F<TInput, P2<TState, TOutput>> getHandler() { | |
return handler; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment