{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_HADDOCK show-extensions #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  ToySolver.Data.BoolExpr
-- Copyright   :  (c) Masahiro Sakai 2014-2015
-- License     :  BSD-style
--
-- Maintainer  :  masahiro.sakai@gmail.com
-- Stability   :  provisional
-- Portability :  non-portable
--
-- Boolean expression over a given type of atoms
--
-----------------------------------------------------------------------------
module ToySolver.Data.BoolExpr
  (
  -- * BoolExpr type
    BoolExpr (..)

  -- * Operations
  , fold
  , simplify
  ) where

import Control.DeepSeq
import Control.Monad
import Data.Data
import Data.Hashable
import Data.Traversable
import ToySolver.Data.Boolean
import ToySolver.Data.IntVar

-- | Boolean expression over a given type of atoms
data BoolExpr a
  = Atom a
  | And [BoolExpr a]
  | Or [BoolExpr a]
  | Not (BoolExpr a)
  | Imply (BoolExpr a) (BoolExpr a)
  | Equiv (BoolExpr a) (BoolExpr a)
  | ITE (BoolExpr a) (BoolExpr a) (BoolExpr a)
  deriving (BoolExpr a -> BoolExpr a -> Bool
(BoolExpr a -> BoolExpr a -> Bool)
-> (BoolExpr a -> BoolExpr a -> Bool) -> Eq (BoolExpr a)
forall a. Eq a => BoolExpr a -> BoolExpr a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BoolExpr a -> BoolExpr a -> Bool
$c/= :: forall a. Eq a => BoolExpr a -> BoolExpr a -> Bool
== :: BoolExpr a -> BoolExpr a -> Bool
$c== :: forall a. Eq a => BoolExpr a -> BoolExpr a -> Bool
Eq, Eq (BoolExpr a)
Eq (BoolExpr a)
-> (BoolExpr a -> BoolExpr a -> Ordering)
-> (BoolExpr a -> BoolExpr a -> Bool)
-> (BoolExpr a -> BoolExpr a -> Bool)
-> (BoolExpr a -> BoolExpr a -> Bool)
-> (BoolExpr a -> BoolExpr a -> Bool)
-> (BoolExpr a -> BoolExpr a -> BoolExpr a)
-> (BoolExpr a -> BoolExpr a -> BoolExpr a)
-> Ord (BoolExpr a)
BoolExpr a -> BoolExpr a -> Bool
BoolExpr a -> BoolExpr a -> Ordering
BoolExpr a -> BoolExpr a -> BoolExpr a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (BoolExpr a)
forall a. Ord a => BoolExpr a -> BoolExpr a -> Bool
forall a. Ord a => BoolExpr a -> BoolExpr a -> Ordering
forall a. Ord a => BoolExpr a -> BoolExpr a -> BoolExpr a
min :: BoolExpr a -> BoolExpr a -> BoolExpr a
$cmin :: forall a. Ord a => BoolExpr a -> BoolExpr a -> BoolExpr a
max :: BoolExpr a -> BoolExpr a -> BoolExpr a
$cmax :: forall a. Ord a => BoolExpr a -> BoolExpr a -> BoolExpr a
>= :: BoolExpr a -> BoolExpr a -> Bool
$c>= :: forall a. Ord a => BoolExpr a -> BoolExpr a -> Bool
> :: BoolExpr a -> BoolExpr a -> Bool
$c> :: forall a. Ord a => BoolExpr a -> BoolExpr a -> Bool
<= :: BoolExpr a -> BoolExpr a -> Bool
$c<= :: forall a. Ord a => BoolExpr a -> BoolExpr a -> Bool
< :: BoolExpr a -> BoolExpr a -> Bool
$c< :: forall a. Ord a => BoolExpr a -> BoolExpr a -> Bool
compare :: BoolExpr a -> BoolExpr a -> Ordering
$ccompare :: forall a. Ord a => BoolExpr a -> BoolExpr a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (BoolExpr a)
Ord, Int -> BoolExpr a -> ShowS
[BoolExpr a] -> ShowS
BoolExpr a -> String
(Int -> BoolExpr a -> ShowS)
-> (BoolExpr a -> String)
-> ([BoolExpr a] -> ShowS)
-> Show (BoolExpr a)
forall a. Show a => Int -> BoolExpr a -> ShowS
forall a. Show a => [BoolExpr a] -> ShowS
forall a. Show a => BoolExpr a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BoolExpr a] -> ShowS
$cshowList :: forall a. Show a => [BoolExpr a] -> ShowS
show :: BoolExpr a -> String
$cshow :: forall a. Show a => BoolExpr a -> String
showsPrec :: Int -> BoolExpr a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> BoolExpr a -> ShowS
Show, ReadPrec [BoolExpr a]
ReadPrec (BoolExpr a)
Int -> ReadS (BoolExpr a)
ReadS [BoolExpr a]
(Int -> ReadS (BoolExpr a))
-> ReadS [BoolExpr a]
-> ReadPrec (BoolExpr a)
-> ReadPrec [BoolExpr a]
-> Read (BoolExpr a)
forall a. Read a => ReadPrec [BoolExpr a]
forall a. Read a => ReadPrec (BoolExpr a)
forall a. Read a => Int -> ReadS (BoolExpr a)
forall a. Read a => ReadS [BoolExpr a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [BoolExpr a]
$creadListPrec :: forall a. Read a => ReadPrec [BoolExpr a]
readPrec :: ReadPrec (BoolExpr a)
$creadPrec :: forall a. Read a => ReadPrec (BoolExpr a)
readList :: ReadS [BoolExpr a]
$creadList :: forall a. Read a => ReadS [BoolExpr a]
readsPrec :: Int -> ReadS (BoolExpr a)
$creadsPrec :: forall a. Read a => Int -> ReadS (BoolExpr a)
Read, Typeable, Typeable (BoolExpr a)
DataType
Constr
Typeable (BoolExpr a)
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BoolExpr a -> c (BoolExpr a))
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (BoolExpr a))
-> (BoolExpr a -> Constr)
-> (BoolExpr a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (BoolExpr a)))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (BoolExpr a)))
-> ((forall b. Data b => b -> b) -> BoolExpr a -> BoolExpr a)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r)
-> (forall u. (forall d. Data d => d -> u) -> BoolExpr a -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> BoolExpr a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a))
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a))
-> Data (BoolExpr a)
BoolExpr a -> DataType
BoolExpr a -> Constr
(forall d. Data d => c (t d)) -> Maybe (c (BoolExpr a))
(forall b. Data b => b -> b) -> BoolExpr a -> BoolExpr a
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BoolExpr a -> c (BoolExpr a)
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (BoolExpr a)
forall a. Data a => Typeable (BoolExpr a)
forall a. Data a => BoolExpr a -> DataType
forall a. Data a => BoolExpr a -> Constr
forall a.
Data a =>
(forall b. Data b => b -> b) -> BoolExpr a -> BoolExpr a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> BoolExpr a -> u
forall a u.
Data a =>
(forall d. Data d => d -> u) -> BoolExpr a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
forall a r r'.
Data a =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (BoolExpr a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BoolExpr a -> c (BoolExpr a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (BoolExpr a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (BoolExpr a))
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> BoolExpr a -> u
forall u. (forall d. Data d => d -> u) -> BoolExpr a -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (BoolExpr a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BoolExpr a -> c (BoolExpr a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (BoolExpr a))
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (BoolExpr a))
$cITE :: Constr
$cEquiv :: Constr
$cImply :: Constr
$cNot :: Constr
$cOr :: Constr
$cAnd :: Constr
$cAtom :: Constr
$tBoolExpr :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
gmapMp :: (forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
gmapM :: (forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> BoolExpr a -> m (BoolExpr a)
gmapQi :: Int -> (forall d. Data d => d -> u) -> BoolExpr a -> u
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> BoolExpr a -> u
gmapQ :: (forall d. Data d => d -> u) -> BoolExpr a -> [u]
$cgmapQ :: forall a u.
Data a =>
(forall d. Data d => d -> u) -> BoolExpr a -> [u]
gmapQr :: (r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
gmapQl :: (r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BoolExpr a -> r
gmapT :: (forall b. Data b => b -> b) -> BoolExpr a -> BoolExpr a
$cgmapT :: forall a.
Data a =>
(forall b. Data b => b -> b) -> BoolExpr a -> BoolExpr a
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (BoolExpr a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c (BoolExpr a))
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (BoolExpr a))
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (BoolExpr a))
dataTypeOf :: BoolExpr a -> DataType
$cdataTypeOf :: forall a. Data a => BoolExpr a -> DataType
toConstr :: BoolExpr a -> Constr
$ctoConstr :: forall a. Data a => BoolExpr a -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (BoolExpr a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (BoolExpr a)
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BoolExpr a -> c (BoolExpr a)
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BoolExpr a -> c (BoolExpr a)
$cp1Data :: forall a. Data a => Typeable (BoolExpr a)
Data)

instance Functor BoolExpr where
  fmap :: (a -> b) -> BoolExpr a -> BoolExpr b
fmap = (a -> b) -> BoolExpr a -> BoolExpr b
forall (t :: * -> *) a b. Traversable t => (a -> b) -> t a -> t b
fmapDefault

instance Applicative BoolExpr where
  pure :: a -> BoolExpr a
pure = a -> BoolExpr a
forall a. a -> BoolExpr a
Atom
  <*> :: BoolExpr (a -> b) -> BoolExpr a -> BoolExpr b
(<*>) = BoolExpr (a -> b) -> BoolExpr a -> BoolExpr b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap

instance Monad BoolExpr where
  return :: a -> BoolExpr a
return = a -> BoolExpr a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  BoolExpr a
m >>= :: BoolExpr a -> (a -> BoolExpr b) -> BoolExpr b
>>= a -> BoolExpr b
f = (a -> BoolExpr b) -> BoolExpr a -> BoolExpr b
forall b atom. Boolean b => (atom -> b) -> BoolExpr atom -> b
fold a -> BoolExpr b
f BoolExpr a
m

instance Foldable BoolExpr where
  foldMap :: (a -> m) -> BoolExpr a -> m
foldMap = (a -> m) -> BoolExpr a -> m
forall (t :: * -> *) m a.
(Traversable t, Monoid m) =>
(a -> m) -> t a -> m
foldMapDefault

instance Traversable BoolExpr where
  traverse :: (a -> f b) -> BoolExpr a -> f (BoolExpr b)
traverse a -> f b
f (Atom a
x) = b -> BoolExpr b
forall a. a -> BoolExpr a
Atom (b -> BoolExpr b) -> f b -> f (BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
x
  traverse a -> f b
f (And [BoolExpr a]
xs) = [BoolExpr b] -> BoolExpr b
forall a. [BoolExpr a] -> BoolExpr a
And ([BoolExpr b] -> BoolExpr b) -> f [BoolExpr b] -> f (BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [f (BoolExpr b)] -> f [BoolExpr b]
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA ((BoolExpr a -> f (BoolExpr b)) -> [BoolExpr a] -> [f (BoolExpr b)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f) [BoolExpr a]
xs)
  traverse a -> f b
f (Or [BoolExpr a]
xs) = [BoolExpr b] -> BoolExpr b
forall a. [BoolExpr a] -> BoolExpr a
Or ([BoolExpr b] -> BoolExpr b) -> f [BoolExpr b] -> f (BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [f (BoolExpr b)] -> f [BoolExpr b]
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA ((BoolExpr a -> f (BoolExpr b)) -> [BoolExpr a] -> [f (BoolExpr b)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f) [BoolExpr a]
xs)
  traverse a -> f b
f (Not BoolExpr a
x) = BoolExpr b -> BoolExpr b
forall a. BoolExpr a -> BoolExpr a
Not (BoolExpr b -> BoolExpr b) -> f (BoolExpr b) -> f (BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
x
  traverse a -> f b
f (Imply BoolExpr a
x BoolExpr a
y) = BoolExpr b -> BoolExpr b -> BoolExpr b
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a
Imply (BoolExpr b -> BoolExpr b -> BoolExpr b)
-> f (BoolExpr b) -> f (BoolExpr b -> BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
x f (BoolExpr b -> BoolExpr b) -> f (BoolExpr b) -> f (BoolExpr b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
y
  traverse a -> f b
f (Equiv BoolExpr a
x BoolExpr a
y) = BoolExpr b -> BoolExpr b -> BoolExpr b
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a
Equiv (BoolExpr b -> BoolExpr b -> BoolExpr b)
-> f (BoolExpr b) -> f (BoolExpr b -> BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
x f (BoolExpr b -> BoolExpr b) -> f (BoolExpr b) -> f (BoolExpr b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
y
  traverse a -> f b
f (ITE BoolExpr a
c BoolExpr a
t BoolExpr a
e) = BoolExpr b -> BoolExpr b -> BoolExpr b -> BoolExpr b
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a -> BoolExpr a
ITE (BoolExpr b -> BoolExpr b -> BoolExpr b -> BoolExpr b)
-> f (BoolExpr b) -> f (BoolExpr b -> BoolExpr b -> BoolExpr b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
c f (BoolExpr b -> BoolExpr b -> BoolExpr b)
-> f (BoolExpr b) -> f (BoolExpr b -> BoolExpr b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
t f (BoolExpr b -> BoolExpr b) -> f (BoolExpr b) -> f (BoolExpr b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (a -> f b) -> BoolExpr a -> f (BoolExpr b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f BoolExpr a
e

instance NFData a => NFData (BoolExpr a) where
  rnf :: BoolExpr a -> ()
rnf (Atom a
a) = a -> ()
forall a. NFData a => a -> ()
rnf a
a
  rnf (And [BoolExpr a]
xs) = [BoolExpr a] -> ()
forall a. NFData a => a -> ()
rnf [BoolExpr a]
xs
  rnf (Or [BoolExpr a]
xs) = [BoolExpr a] -> ()
forall a. NFData a => a -> ()
rnf [BoolExpr a]
xs
  rnf (Not BoolExpr a
x) = BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
x
  rnf (Imply BoolExpr a
x BoolExpr a
y) = BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
x () -> () -> ()
`seq` BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
y
  rnf (Equiv BoolExpr a
x BoolExpr a
y) = BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
x () -> () -> ()
`seq` BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
y
  rnf (ITE BoolExpr a
c BoolExpr a
t BoolExpr a
e) = BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
c () -> () -> ()
`seq` BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
t () -> () -> ()
`seq` BoolExpr a -> ()
forall a. NFData a => a -> ()
rnf BoolExpr a
e

instance Hashable a => Hashable (BoolExpr a) where
  hashWithSalt :: Int -> BoolExpr a -> Int
hashWithSalt Int
s (Atom a
a) = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
0::Int) Int -> a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` a
a
  hashWithSalt Int
s (And [BoolExpr a]
xs) = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
1::Int) Int -> [BoolExpr a] -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` [BoolExpr a]
xs
  hashWithSalt Int
s (Or [BoolExpr a]
xs)  = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
2::Int) Int -> [BoolExpr a] -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` [BoolExpr a]
xs
  hashWithSalt Int
s (Not BoolExpr a
x)  = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
3::Int) Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
x
  hashWithSalt Int
s (Imply BoolExpr a
x BoolExpr a
y) = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
4::Int) Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
x Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
y
  hashWithSalt Int
s (Equiv BoolExpr a
x BoolExpr a
y) = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
5::Int) Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
x Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
y
  hashWithSalt Int
s (ITE BoolExpr a
c BoolExpr a
t BoolExpr a
e) = Int
s Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` (Int
6::Int) Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
c Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
t Int -> BoolExpr a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` BoolExpr a
e

instance Complement (BoolExpr a) where
  notB :: BoolExpr a -> BoolExpr a
notB = BoolExpr a -> BoolExpr a
forall a. BoolExpr a -> BoolExpr a
Not

instance MonotoneBoolean (BoolExpr a) where
  andB :: [BoolExpr a] -> BoolExpr a
andB = [BoolExpr a] -> BoolExpr a
forall a. [BoolExpr a] -> BoolExpr a
And
  orB :: [BoolExpr a] -> BoolExpr a
orB  = [BoolExpr a] -> BoolExpr a
forall a. [BoolExpr a] -> BoolExpr a
Or

instance IfThenElse (BoolExpr a) (BoolExpr a) where
  ite :: BoolExpr a -> BoolExpr a -> BoolExpr a -> BoolExpr a
ite = BoolExpr a -> BoolExpr a -> BoolExpr a -> BoolExpr a
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a -> BoolExpr a
ITE

instance Boolean (BoolExpr a) where
  .=>. :: BoolExpr a -> BoolExpr a -> BoolExpr a
(.=>.) = BoolExpr a -> BoolExpr a -> BoolExpr a
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a
Imply
  .<=>. :: BoolExpr a -> BoolExpr a -> BoolExpr a
(.<=>.) = BoolExpr a -> BoolExpr a -> BoolExpr a
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a
Equiv

instance Variables a => Variables (BoolExpr a) where
  vars :: BoolExpr a -> VarSet
vars = (a -> VarSet) -> BoolExpr a -> VarSet
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> VarSet
forall a. Variables a => a -> VarSet
vars


fold :: Boolean b => (atom -> b) -> BoolExpr atom -> b
fold :: (atom -> b) -> BoolExpr atom -> b
fold atom -> b
f = BoolExpr atom -> b
g
  where
    g :: BoolExpr atom -> b
g (Atom atom
a) = atom -> b
f atom
a
    g (Or [BoolExpr atom]
xs) = [b] -> b
forall a. MonotoneBoolean a => [a] -> a
orB ((BoolExpr atom -> b) -> [BoolExpr atom] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map BoolExpr atom -> b
g [BoolExpr atom]
xs)
    g (And [BoolExpr atom]
xs) = [b] -> b
forall a. MonotoneBoolean a => [a] -> a
andB ((BoolExpr atom -> b) -> [BoolExpr atom] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map BoolExpr atom -> b
g [BoolExpr atom]
xs)
    g (Not BoolExpr atom
x) = b -> b
forall a. Complement a => a -> a
notB (BoolExpr atom -> b
g BoolExpr atom
x)
    g (Imply BoolExpr atom
x BoolExpr atom
y) = BoolExpr atom -> b
g BoolExpr atom
x b -> b -> b
forall a. Boolean a => a -> a -> a
.=>. BoolExpr atom -> b
g BoolExpr atom
y
    g (Equiv BoolExpr atom
x BoolExpr atom
y) = BoolExpr atom -> b
g BoolExpr atom
x b -> b -> b
forall a. Boolean a => a -> a -> a
.<=>. BoolExpr atom -> b
g BoolExpr atom
y
    g (ITE BoolExpr atom
c BoolExpr atom
t BoolExpr atom
e) = b -> b -> b -> b
forall b a. IfThenElse b a => b -> a -> a -> a
ite (BoolExpr atom -> b
g BoolExpr atom
c) (BoolExpr atom -> b
g BoolExpr atom
t) (BoolExpr atom -> b
g BoolExpr atom
e)

{-# RULES
  "fold/fmap"    forall f g e.  fold f (fmap g e) = fold (f.g) e
 #-}

instance Eval m a Bool => Eval m (BoolExpr a) Bool where
  eval :: m -> BoolExpr a -> Bool
eval m
m = (a -> Bool) -> BoolExpr a -> Bool
forall b atom. Boolean b => (atom -> b) -> BoolExpr atom -> b
fold (m -> a -> Bool
forall m e v. Eval m e v => m -> e -> v
eval m
m)

simplify :: BoolExpr a -> BoolExpr a
simplify :: BoolExpr a -> BoolExpr a
simplify = Simplify a -> BoolExpr a
forall a. Simplify a -> BoolExpr a
runSimplify (Simplify a -> BoolExpr a)
-> (BoolExpr a -> Simplify a) -> BoolExpr a -> BoolExpr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Simplify a) -> BoolExpr a -> Simplify a
forall b atom. Boolean b => (atom -> b) -> BoolExpr atom -> b
fold (BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify (BoolExpr a -> Simplify a) -> (a -> BoolExpr a) -> a -> Simplify a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> BoolExpr a
forall a. a -> BoolExpr a
Atom)

newtype Simplify a = Simplify{ Simplify a -> BoolExpr a
runSimplify :: BoolExpr a }

instance Complement (Simplify a) where
  notB :: Simplify a -> Simplify a
notB (Simplify (Not BoolExpr a
x)) = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
x
  notB (Simplify BoolExpr a
x) = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify (BoolExpr a -> BoolExpr a
forall a. BoolExpr a -> BoolExpr a
Not BoolExpr a
x)

instance MonotoneBoolean (Simplify a) where
  orB :: [Simplify a] -> Simplify a
orB [Simplify a]
xs
    | (BoolExpr a -> Bool) -> [BoolExpr a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isTrue [BoolExpr a]
ys = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
forall a. MonotoneBoolean a => a
true
    | Bool
otherwise = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify (BoolExpr a -> Simplify a) -> BoolExpr a -> Simplify a
forall a b. (a -> b) -> a -> b
$ [BoolExpr a] -> BoolExpr a
forall a. [BoolExpr a] -> BoolExpr a
Or [BoolExpr a]
ys
    where
      ys :: [BoolExpr a]
ys = [[BoolExpr a]] -> [BoolExpr a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [BoolExpr a -> [BoolExpr a]
forall a. BoolExpr a -> [BoolExpr a]
f BoolExpr a
x | Simplify BoolExpr a
x <- [Simplify a]
xs]
      f :: BoolExpr a -> [BoolExpr a]
f (Or [BoolExpr a]
zs) = [BoolExpr a]
zs
      f BoolExpr a
z = [BoolExpr a
z]
  andB :: [Simplify a] -> Simplify a
andB [Simplify a]
xs
    | (BoolExpr a -> Bool) -> [BoolExpr a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isFalse [BoolExpr a]
ys = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
forall a. MonotoneBoolean a => a
false
    | Bool
otherwise = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify (BoolExpr a -> Simplify a) -> BoolExpr a -> Simplify a
forall a b. (a -> b) -> a -> b
$ [BoolExpr a] -> BoolExpr a
forall a. [BoolExpr a] -> BoolExpr a
And [BoolExpr a]
ys
    where
      ys :: [BoolExpr a]
ys = [[BoolExpr a]] -> [BoolExpr a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [BoolExpr a -> [BoolExpr a]
forall a. BoolExpr a -> [BoolExpr a]
f BoolExpr a
x | Simplify BoolExpr a
x <- [Simplify a]
xs]
      f :: BoolExpr a -> [BoolExpr a]
f (And [BoolExpr a]
zs) = [BoolExpr a]
zs
      f BoolExpr a
z = [BoolExpr a
z]

instance IfThenElse (Simplify a) (Simplify a) where
  ite :: Simplify a -> Simplify a -> Simplify a -> Simplify a
ite (Simplify BoolExpr a
c) (Simplify BoolExpr a
t) (Simplify BoolExpr a
e)
    | BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isTrue BoolExpr a
c  = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
t
    | BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isFalse BoolExpr a
c = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
e
    | Bool
otherwise = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify (BoolExpr a -> BoolExpr a -> BoolExpr a -> BoolExpr a
forall a. BoolExpr a -> BoolExpr a -> BoolExpr a -> BoolExpr a
ITE BoolExpr a
c BoolExpr a
t BoolExpr a
e)

instance Boolean (Simplify a) where
  Simplify BoolExpr a
x .=>. :: Simplify a -> Simplify a -> Simplify a
.=>. Simplify BoolExpr a
y
    | BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isFalse BoolExpr a
x = Simplify a
forall a. MonotoneBoolean a => a
true
    | BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isTrue BoolExpr a
y  = Simplify a
forall a. MonotoneBoolean a => a
true
    | BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isTrue BoolExpr a
x  = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
y
    | BoolExpr a -> Bool
forall a. BoolExpr a -> Bool
isFalse BoolExpr a
y = Simplify a -> Simplify a
forall a. Complement a => a -> a
notB (BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify BoolExpr a
x)
    | Bool
otherwise = BoolExpr a -> Simplify a
forall a. BoolExpr a -> Simplify a
Simplify (BoolExpr a
x BoolExpr a -> BoolExpr a -> BoolExpr a
forall a. Boolean a => a -> a -> a
.=>. BoolExpr a
y)

isTrue :: BoolExpr a -> Bool
isTrue :: BoolExpr a -> Bool
isTrue (And []) = Bool
True
isTrue BoolExpr a
_ = Bool
False

isFalse :: BoolExpr a -> Bool
isFalse :: BoolExpr a -> Bool
isFalse (Or []) = Bool
True
isFalse BoolExpr a
_ = Bool
False