ghc-9.14.1: Language/Haskell/Syntax/BooleanFormula.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Language.Haskell.Syntax.BooleanFormula(
BooleanFormula(..), LBooleanFormula,
mkVar, mkFalse, mkTrue, mkBool, mkAnd, mkOr
) where
import Prelude hiding ( init, last )
import Data.List ( nub )
import Language.Haskell.Syntax.Extension (XRec, UnXRec (..), LIdP)
-- types
type LBooleanFormula p = XRec p (BooleanFormula p)
data BooleanFormula p = Var (LIdP p) | And [LBooleanFormula p] | Or [LBooleanFormula p]
| Parens (LBooleanFormula p)
-- instances
deriving instance (Eq (LIdP p), Eq (LBooleanFormula p)) => Eq (BooleanFormula p)
-- smart constructors
-- see note [Simplification of BooleanFormulas]
mkVar :: LIdP p -> BooleanFormula p
mkVar = Var
mkFalse, mkTrue :: BooleanFormula p
mkFalse = Or []
mkTrue = And []
-- Convert a Bool to a BooleanFormula
mkBool :: Bool -> BooleanFormula p
mkBool False = mkFalse
mkBool True = mkTrue
-- Make a conjunction, and try to simplify
mkAnd :: forall p. (UnXRec p, Eq (LIdP p), Eq (LBooleanFormula p)) => [LBooleanFormula p] -> BooleanFormula p
mkAnd = maybe mkFalse (mkAnd' . nub . concat) . mapM fromAnd
where
-- See Note [Simplification of BooleanFormulas]
fromAnd :: LBooleanFormula p -> Maybe [LBooleanFormula p]
fromAnd bf = case unXRec @p bf of
(And xs) -> Just xs
-- assume that xs are already simplified
-- otherwise we would need: fromAnd (And xs) = concat <$> traverse fromAnd xs
(Or []) -> Nothing
-- in case of False we bail out, And [..,mkFalse,..] == mkFalse
_ -> Just [bf]
mkAnd' [x] = unXRec @p x
mkAnd' xs = And xs
mkOr :: forall p. (UnXRec p, Eq (LIdP p), Eq (LBooleanFormula p)) => [LBooleanFormula p] -> BooleanFormula p
mkOr = maybe mkTrue (mkOr' . nub . concat) . mapM fromOr
where
-- See Note [Simplification of BooleanFormulas]
fromOr bf = case unXRec @p bf of
(Or xs) -> Just xs
(And []) -> Nothing
_ -> Just [bf]
mkOr' [x] = unXRec @p x
mkOr' xs = Or xs