Safe Haskell | None |
---|---|
Language | Haskell2010 |
Simple Constraint solver
Synopsis
- data PredState
- type PredOracle p = Map p PredState
- makeOracle :: Ord p => [(p, PredState)] -> PredOracle p
- oraclePredicates :: Ord p => PredOracle p -> [(p, PredState)]
- emptyOracle :: PredOracle p
- oracleUnion :: Ord p => PredOracle p -> PredOracle p -> PredOracle p
- predIsSet :: Ord p => PredOracle p -> p -> Bool
- predIsUnset :: Ord p => PredOracle p -> p -> Bool
- predIsUndef :: Ord p => PredOracle p -> p -> Bool
- predIsInvalid :: Ord p => PredOracle p -> p -> Bool
- predIs :: Ord p => PredOracle p -> p -> PredState -> Bool
- predState :: Ord p => PredOracle p -> p -> PredState
- predAdd :: Ord p => [(p, PredState)] -> PredOracle p -> PredOracle p
- data Constraint e p
- = Predicate p
- | IsValid p
- | Not (Constraint e p)
- | And [Constraint e p]
- | Or [Constraint e p]
- | Xor [Constraint e p]
- | CBool Bool
- | CErr (Either String e)
- constraintOptimize :: Constraint e p -> Constraint e p
- constraintSimplify :: (Ord p, Eq p, Eq e) => PredOracle p -> Constraint e p -> Constraint e p
- data Rule e p a
- = Terminal a
- | OrderedNonTerminal [(Constraint e p, Rule e p a)]
- | NonTerminal [(Constraint e p, Rule e p a)]
- | Fail e
- ruleSimplify :: (Ord p, Eq e) => PredOracle p -> Rule e p a -> Rule e p a
- evalsTo :: (Ord (Pred a), Eq a, Eq (PredTerm a), Eq (Pred a), Predicated a) => a -> PredTerm a -> Constraint e (Pred a)
- data MatchResult e nt t
- = NoMatch
- | Match t
- | DontMatch nt
- | MatchFail [e]
- | MatchDiverge [nt]
- class (Ord (Pred a), Ord (PredTerm a)) => Predicated a where
- type PredErr a :: *
- type Pred a :: *
- type PredTerm a :: *
- liftTerminal :: PredTerm a -> a
- reducePredicates :: PredOracle (Pred a) -> a -> MatchResult (PredErr a) a (PredTerm a)
- simplifyPredicates :: PredOracle (Pred a) -> a -> a
- getTerminals :: a -> Set (PredTerm a)
- getPredicates :: a -> Set (Pred a)
- createPredicateTable :: (Ord (Pred a), Eq (Pred a), Eq a, Predicated a, Predicated a, Pred a ~ Pred a) => a -> (PredOracle (Pred a) -> Bool) -> Either (PredTerm a) [(PredOracle (Pred a), PredTerm a)]
- initP :: nt -> t -> MatchResult e nt (nt, t)
- applyP :: Predicated ntb => MatchResult e (ntb -> nt) (ntb -> nt, PredTerm ntb -> t) -> MatchResult e ntb (PredTerm ntb) -> MatchResult e nt (nt, t)
- resultP :: MatchResult e nt (nt, t) -> MatchResult e nt t
Oracle
Predicate state
SetPred | Set predicate |
UnsetPred | Unset predicate |
UndefPred | Undefined predicate |
InvalidPred | Invalid predicate (can't be used) |
type PredOracle p = Map p PredState Source #
Predicate oracle
makeOracle :: Ord p => [(p, PredState)] -> PredOracle p Source #
Create an oracle from a list
oraclePredicates :: Ord p => PredOracle p -> [(p, PredState)] Source #
Get a list of valid and defined predicates from an oracle
emptyOracle :: PredOracle p Source #
Oracle that always answer Undef
oracleUnion :: Ord p => PredOracle p -> PredOracle p -> PredOracle p Source #
Combine two oracles TODO: check that there is no contradiction
predIsUnset :: Ord p => PredOracle p -> p -> Bool Source #
Ask an oracle if a predicate is unset
predIsUndef :: Ord p => PredOracle p -> p -> Bool Source #
Ask an oracle if a predicate is undefined
predIsInvalid :: Ord p => PredOracle p -> p -> Bool Source #
Ask an oracle if a predicate is invalid
predAdd :: Ord p => [(p, PredState)] -> PredOracle p -> PredOracle p Source #
Add predicates to an oracle TODO: check that there is no contradiction
Constraint
data Constraint e p Source #
A constraint is a boolean expression
p
is the predicate type
Predicate p | Predicate value |
IsValid p | Is the predicate valid |
Not (Constraint e p) | Logic not |
And [Constraint e p] | Logic and |
Or [Constraint e p] | Logic or |
Xor [Constraint e p] | Logic xor |
CBool Bool | Constant |
CErr (Either String e) | Error |
Instances
constraintOptimize :: Constraint e p -> Constraint e p Source #
Optimize/simplify a constraint
constraintSimplify :: (Ord p, Eq p, Eq e) => PredOracle p -> Constraint e p -> Constraint e p Source #
Reduce a constraint
>>>
data P = A | B deriving (Show,Eq,Ord)
>>>
let c = And [IsValid A, Predicate B]
>>>
let oracle = makeOracle [(A,InvalidPred),(B,SetPred)]
>>>
constraintSimplify oracle c
CBool False
>>>
let oracle = makeOracle [(A,SetPred),(B,SetPred)]
>>>
constraintSimplify oracle c
CBool True
>>>
let oracle = makeOracle [(A,SetPred),(B,UnsetPred)]
>>>
constraintSimplify oracle c
CBool False
Rule
A rule can produce some "a"s (one or more if it diverges), depending on the constraints.
Terminal a | |
OrderedNonTerminal [(Constraint e p, Rule e p a)] | |
NonTerminal [(Constraint e p, Rule e p a)] | |
Fail e |
Instances
Functor (Rule e p) Source # | |
(Eq a, Eq p, Eq e) => Eq (Rule e p a) Source # | |
(Ord a, Ord p, Ord e) => Ord (Rule e p a) Source # | |
(Show a, Show p, Show e) => Show (Rule e p a) Source # | |
(Ord a, Ord p, Eq e, Eq a, Eq p) => Predicated (Rule e p a) Source # | |
Defined in Haskus.Utils.Solver liftTerminal :: PredTerm (Rule e p a) -> Rule e p a Source # reducePredicates :: PredOracle (Pred (Rule e p a)) -> Rule e p a -> MatchResult (PredErr (Rule e p a)) (Rule e p a) (PredTerm (Rule e p a)) Source # simplifyPredicates :: PredOracle (Pred (Rule e p a)) -> Rule e p a -> Rule e p a Source # getTerminals :: Rule e p a -> Set (PredTerm (Rule e p a)) Source # getPredicates :: Rule e p a -> Set (Pred (Rule e p a)) Source # | |
type PredErr (Rule e p a) Source # | |
Defined in Haskus.Utils.Solver | |
type Pred (Rule e p a) Source # | |
Defined in Haskus.Utils.Solver | |
type PredTerm (Rule e p a) Source # | |
Defined in Haskus.Utils.Solver |
ruleSimplify :: (Ord p, Eq e) => PredOracle p -> Rule e p a -> Rule e p a Source #
Simplify a rule given an oracle
evalsTo :: (Ord (Pred a), Eq a, Eq (PredTerm a), Eq (Pred a), Predicated a) => a -> PredTerm a -> Constraint e (Pred a) Source #
Constraint checking that a predicated value evaluates to some terminal
data MatchResult e nt t Source #
Reduction result
NoMatch | |
Match t | |
DontMatch nt | |
MatchFail [e] | |
MatchDiverge [nt] |
Instances
Predicated data
class (Ord (Pred a), Ord (PredTerm a)) => Predicated a where Source #
Predicated data
data T data NT type family RuleT e p a s :: * where RuleT e p a T = a RuleT e p a NT = Rule e p a data PD t = PD { p1 :: RuleT () Bool Int t , p2 :: RuleT () Bool String t } deriving instance Eq (PD T) deriving instance Show (PD T) deriving instance Ord (PD T) deriving instance Eq (PD NT) deriving instance Show (PD NT) deriving instance Ord (PD NT) instance Predicated (PD NT) where type PredErr (PD NT) = () type Pred (PD NT) = Bool type PredTerm (PD NT) = PD T liftTerminal (PD a b) = PD (liftTerminal a) (liftTerminal b) reducePredicates oracle (PD a b) = initP PD PD |> (applyP
reducePredicates oracle a) |> (applyP
reducePredicates oracle b) |> resultP getTerminals (PD as bs) = [ PD a b | a <- getTerminals as , b <- getTerminals bs ] getPredicates (PD a b) = concat [ getPredicates a , getPredicates b ]
Error type
Predicate type
Terminal type
liftTerminal :: PredTerm a -> a Source #
Build a non terminal from a terminal
reducePredicates :: PredOracle (Pred a) -> a -> MatchResult (PredErr a) a (PredTerm a) Source #
Reduce predicates
simplifyPredicates :: PredOracle (Pred a) -> a -> a Source #
Simplify predicates
getTerminals :: a -> Set (PredTerm a) Source #
Get possible resulting terminals
getPredicates :: a -> Set (Pred a) Source #
Get used predicates
Instances
createPredicateTable :: (Ord (Pred a), Eq (Pred a), Eq a, Predicated a, Predicated a, Pred a ~ Pred a) => a -> (PredOracle (Pred a) -> Bool) -> Either (PredTerm a) [(PredOracle (Pred a), PredTerm a)] Source #
Create a table of predicates that return a terminal
initP :: nt -> t -> MatchResult e nt (nt, t) Source #
Initialise a reduction result (typically with two functions/constructors)
applyP :: Predicated ntb => MatchResult e (ntb -> nt) (ntb -> nt, PredTerm ntb -> t) -> MatchResult e ntb (PredTerm ntb) -> MatchResult e nt (nt, t) Source #
Compose reduction results
We reuse the MatchResult data type: * a "terminal" on the left can be used to build either a terminal or a non terminal * a "non terminal" on the left can only be used to build a non terminal
resultP :: MatchResult e nt (nt, t) -> MatchResult e nt t Source #
Fixup result (see initP and applyP)