{-# LANGUAGE CPP, OverloadedLists, TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module : Algebra.Graph.Labelled.Example.Automaton -- Copyright : (c) Andrey Mokhov 2016-2018 -- License : MIT (see the file LICENSE) -- Maintainer : andrey.mokhov@gmail.com -- Stability : experimental -- -- __Alga__ is a library for algebraic construction and manipulation of graphs -- in Haskell. See for the -- motivation behind the library, the underlying theory, and implementation details. -- -- This module contains a simple example of using edge-labelled graphs defined -- in the module "Algebra.Graph.Labelled" for working with finite automata. ----------------------------------------------------------------------------- module Algebra.Graph.Labelled.Example.Automaton where import Data.Map (Map) import Data.Monoid (Any (..)) import Algebra.Graph.Label import Algebra.Graph.Labelled import Algebra.Graph.ToGraph import qualified Data.Map as Map #if !MIN_VERSION_base(4,8,0) import Data.Set (Set) import qualified Data.Set as Set import GHC.Exts hiding (Any) instance Ord a => IsList (Set a) where type Item (Set a) = a fromList = Set.fromList toList = Set.toList #endif -- | The alphabet of actions for ordering coffee or tea. data Alphabet = Coffee -- ^ Order coffee | Tea -- ^ Order tea | Cancel -- ^ Cancel payment or order | Pay -- ^ Pay for the order deriving (Bounded, Enum, Eq, Ord, Show) -- | The state of the order. data State = Choice -- ^ Choosing what to order | Payment -- ^ Making the payment | Complete -- ^ The order is complete deriving (Bounded, Enum, Eq, Ord, Show) -- TODO: Add an illustration. -- | An example automaton for ordering coffee or tea. -- -- @ -- order = 'overlays' [ 'Choice' '-<'['Coffee', 'Tea']'>-' 'Payment' -- , 'Choice' '-<'['Cancel' ]'>-' 'Complete' -- , 'Payment' '-<'['Cancel' ]'>-' 'Choice' -- , 'Payment' '-<'['Pay' ]'>-' 'Complete' ] -- @ coffeeTeaAutomaton :: Automaton Alphabet State coffeeTeaAutomaton = overlays [ Choice -<[Coffee, Tea]>- Payment , Payment -<[Pay ]>- Complete , Choice -<[Cancel ]>- Complete , Payment -<[Cancel ]>- Choice ] -- | The map of 'State' reachability. -- -- @ -- reachability = Map.'Map.fromList' $ map (\s -> (s, 'reachable' s 'order')) ['Choice' ..] -- @ -- -- Or, when evaluated: -- -- @ -- reachability = Map.'Map.fromList' [ ('Choice' , ['Choice' , 'Payment', 'Complete']) -- , ('Payment' , ['Payment' , 'Choice' , 'Complete']) -- , ('Complete', ['Complete' ]) ] -- @ reachability :: Map State [State] reachability = Map.fromList $ map (\s -> (s, reachable s skeleton)) [Choice ..] where skeleton :: Graph Any State skeleton = emap (Any . not . isZero) coffeeTeaAutomaton