packages feed

haal-0.2.0.0: src/Haal/Automaton/MooreAutomaton.hs

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | This module implements a Moore automaton.
module Haal.Automaton.MooreAutomaton (
    MooreAutomaton,
    mkMooreAutomaton,
    mooreTransitions,
)
where

import qualified Data.Map as Map
import qualified Data.Set as Set
import Haal.BlackBox
import Control.Monad.Identity (Identity)

data MooreAutomaton state input output = MooreAutomaton
    { mooreDelta :: state -> input -> state
    , mooreLambda :: state -> output
    , mooreInitialS :: state
    , mooreCurrentS :: state
    , mooreStates :: Set.Set state
    }

{- | The 'mkMooreAutomaton' constructor returns a 'MooreAutomaton' by requiring the 'mooreDelta'
function, the 'mooreLambda' function and the initial state 'mooreInitialS'.
-}
mkMooreAutomaton :: (s -> i -> s) -> (s -> o) -> Set.Set s -> s -> MooreAutomaton s i o
mkMooreAutomaton delta lambda sts initS =
    MooreAutomaton
        { mooreDelta = delta
        , mooreLambda = lambda
        , mooreInitialS = initS
        , mooreCurrentS = initS
        , mooreStates = sts
        }

{- | Performs a step in the automaton and returns a tuple containing the automaton with a modified
state as well as the output produced by the transition.
-}
mooreStep :: MooreAutomaton s i o -> i -> (MooreAutomaton s i o, o)
mooreStep m i = (m{mooreCurrentS = nextState}, output)
  where
    nextState = mooreDelta m (mooreCurrentS m) i
    output = mooreLambda m (mooreCurrentS m)

-- | Resets the automaton to its initial state.
mooreReset :: MooreAutomaton s i o -> MooreAutomaton s i o
mooreReset m = m{mooreCurrentS = mooreInitialS m}

instance SUL (MooreAutomaton s) Identity i o where
    step sul i = return (mooreStep sul i)
    reset = return . mooreReset

{- | Returns a map describing the combined behaviour of the 'mooreDelta'
and 'mooreLambda' functions.
-}
mooreTransitions ::
    forall i o s.
    (FiniteOrd s, FiniteOrd i) =>
    MooreAutomaton s i o ->
    Map.Map (s, i) (s, o)
mooreTransitions m = Map.fromList [((s, i), (delta s i, lambda s)) | s <- domainS, i <- domainI]
  where
    delta = mooreDelta m
    lambda = mooreLambda m
    domainS = Set.toList $ mooreStates m
    domainI = Set.toList $ inputs m

instance Automaton MooreAutomaton s i o where
    transitions = mooreTransitions
    current = mooreCurrentS
    states = mooreStates
    update m s = m{mooreCurrentS = s}

instance
    ( Show i
    , Show o
    , Show s
    , FiniteOrd s
    , FiniteOrd i
    ) =>
    Show (MooreAutomaton s i o)
    where
    show m =
        "{\n\tCurrent State: "
            ++ show currentS
            ++ ",\n\tInitial State: "
            ++ show initialS
            ++ ",\n\tTransitions: "
            ++ show transs
            ++ "\n}"
      where
        transs = mooreTransitions m
        initialS = initial m
        currentS = current m