{-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE TypeOperators #-} {-| Module : Data.Delta Description : Partial functions Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016 License : GPL-3 Maintainer : sanjorgek@ciencias.unam.mx Stability : experimental Portability : portable Map implementation, represent a partial function -} module Data.Delta ( -- * Delta -- ** Generic (:*>:)(..) -- ** Deterministic -- *** Constructor ,(:->:)(..) -- *** Functions ,liftD ,nextD -- ** Not deterministic -- *** Constructor ,(:-<:)(..) -- *** Functions ,liftND ,nextND -- ** Functions ,liftL ,nextTMaybe ,nextSymbol -- * Auxiliar functions ,getFirstParam ,getFirstParamSet ,getSecondParamD ,getSecondParamND ,getSecondParamSetD ,getSecondParamSetND ,getStateDomain ,getStateDomainSet ,getStateRangeD ,getStateRangeND ,getStateRangeSetD ,getStateRangeSetND ) where import qualified Data.Foldable as Fold import Data.Label import Data.List import qualified Data.Map.Strict as Map import Data.Maybe import qualified Data.Set as Set import Data.Sigma {-| Map a tuple, a state and a param, to some output -} type (:*>:) a p o = Map.Map (Label a, p) o {-| Lift a generic delta/map from a 3-tuple list -} liftL :: (Ord a, Ord p) => [(a, p, o)] -> (:*>:) a p o liftL ds = let (xs, ys, zs) = unzip3 ds in Map.fromList $ zip (zip (fmap return xs) ys) zs {-| Take a state and a param and maybe resolve some output -} nextTMaybe :: (Ord p1, Ord a) => (:*>:) a p1 o -> (Label a, p1) -> Maybe o nextTMaybe dt k = if Map.member k dt then Just $ dt Map.! k else Nothing {-| For simple map with Chars range -} nextSymbol::(Ord p1, Ord a) => (:*>:) a p1 Symbol -> (Label a, p1) -> Symbol nextSymbol dt k = fromMaybe '\NUL' $ nextTMaybe dt k {-| Deterministic Delta Maps a tuple, a state and a param, to another tuple, a state and a param. -} type (:->:) a p1 p2 = (:*>:) a p1 (Label a, p2) {-| Lifts a deterministic delta from a 4-tuple list -} liftD::(Ord a, Ord p1) => [(a, p1, a, p2)] -> (:->:) a p1 p2 liftD ds = let (xs, ys, ws, zs) = unzip4 ds in liftL $ zip3 xs ys $ zip (fmap return ws) zs {-| Next state function for deterministic delta -} nextD :: (Ord p1, Ord a) => (:->:) a p1 p2 -> (Label a, p1) -> Label a nextD dt k = maybe QE fst $ nextTMaybe dt k {-| Non-Deterministic Delta Maps a tuple, a state and a param, to a tuple, a state list and a param. -} type (:-<:) a p1 p2 = (:*>:) a p1 (Set.Set (Label a, p2)) {-| Lifts a non-deterministic delta from a 4-tuple list -} liftND::(Ord a, Ord p1, Ord p2) => [(a, p1, [(a,p2)])] -> (:-<:) a p1 p2 liftND ds = let (xs, ys, wss) = unzip3 ds f (x,y) = (return x, y) in liftL $ zip3 xs ys $ fmap (Set.fromList . fmap f) wss {-| Next state function for non-deterministic delta -} nextND :: (Ord p1, Ord a) => (:-<:) a p1 p2 -> p2 -> (Label a, p1) -> Set.Set (Label a) nextND dt p k = maybe (Set.singleton QE) (Set.map fst) $ nextTMaybe dt k {-| Gets all params at domain, for (:->:) and (:-<:) -} getFirstParam::(Eq b) => Map.Map (a, b) a1 -> [b] getFirstParam = nub . fmap snd . Map.keys {-| Gets all params at domain, for (:-<:) and (:-<:) -} getFirstParamSet::(Ord b) => Map.Map (a, b) a1 -> Set.Set b getFirstParamSet = Set.fromList . fmap snd . Map.keys {-| Gets all states at domain, for (:->:) and (:-<:) -} getStateDomain::(Eq a) => Map.Map (a, b) a1 -> [a] getStateDomain = nub . fmap fst . Map.keys {-| Gets all states at domain, for (:->:) and (:-<:) -} getStateDomainSet::(Ord a) => Map.Map (a, b) a1 -> Set.Set a getStateDomainSet = Set.fromList . fmap fst . Map.keys {-| Gets all params at range, for (:->:) -} getSecondParamD::(Eq p2) => (:->:) a p1 p2 -> [p2] getSecondParamD = nub . fmap snd . Map.elems {-| Gets all params at range, for (:->:) -} getSecondParamSetD::(Ord b) => Map.Map k (a, b) -> Set.Set b getSecondParamSetD = Set.fromList . fmap snd . Map.elems {-| Gets all params at range, for (:-<:) -} getSecondParamND::(Ord p2) => (:-<:) a p1 p2 -> [p2] getSecondParamND = foldr union [] . fmap (Set.toList . Set.map snd) . Map.elems {-| Gets all params at range, for (:-<:) -} getSecondParamSetND::(Ord p2) => (:-<:) a p1 p2 -> Set.Set p2 getSecondParamSetND = Set.unions . fmap (Set.map snd) . Map.elems {-| Gets first param at range, for (:->:) -} getStateRangeD::(Eq a) => (:->:) a p1 p2 -> [Label a] getStateRangeD = nub . fmap fst . Map.elems {-| Gets first param at range, for (:->:) -} getStateRangeSetD::(Ord a) => (:->:) a p1 p2 -> Set.Set (Label a) getStateRangeSetD = Set.fromList . fmap fst . Map.elems {-| Gets state at range in a list, for (:-<:) -} getStateRangeND::(Ord a) => (:-<:) a p1 p2 -> [Label a] getStateRangeND = Set.toList . Set.unions . fmap (Set.map fst) . Map.elems {-| Gets state at range in a set, for (:-<:) -} getStateRangeSetND::(Ord a) => (:-<:) a p1 p2 -> Set.Set (Label a) getStateRangeSetND = Set.unions . fmap (Set.map fst) . Map.elems