{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Language.Expression.Prop
(
Prop
, Prop'
, expr
, plit
, pnot
, (*&&)
, (*||)
, (*->)
, (*<->)
, propAnd
, propOr
, LogicOp(..)
) where
import Control.Applicative (liftA2)
import Data.List (foldl')
import Data.Functor.Identity
import Data.SBV
import Language.Expression
import Language.Expression.Choice
import Language.Expression.Pretty
import Language.Expression.Util
type Prop = HFree LogicOp
type Prop' ops v = Prop (HFree' ops v)
infixl 3 *&&
infixl 2 *||
infixr 1 *->
infix 1 *<->
expr :: expr a -> Prop expr a
expr = HPure
plit :: Bool -> Prop expr Bool
plit = HWrap . LogLit
pnot :: Prop expr Bool -> Prop expr Bool
pnot = HWrap . LogNot
(*&&) :: Prop expr Bool -> Prop expr Bool -> Prop expr Bool
(*&&) = HWrap ... LogAnd
(*||) :: Prop expr Bool -> Prop expr Bool -> Prop expr Bool
(*||) = HWrap ... LogOr
(*->) :: Prop expr Bool -> Prop expr Bool -> Prop expr Bool
(*->) = HWrap ... LogImpl
(*<->) :: Prop expr Bool -> Prop expr Bool -> Prop expr Bool
(*<->) = HWrap ... LogEquiv
propAnd :: [Prop expr Bool] -> Prop expr Bool
propAnd [] = plit True
propAnd (x : xs) = foldl' (*&&) x xs
propOr :: [Prop expr Bool] -> Prop expr Bool
propOr [] = plit False
propOr (x : xs) = foldl' (*||) x xs
data LogicOp t a where
LogLit :: Bool -> LogicOp t Bool
LogNot :: t Bool -> LogicOp t Bool
LogAnd :: t Bool -> t Bool -> LogicOp t Bool
LogOr :: t Bool -> t Bool -> LogicOp t Bool
LogImpl :: t Bool -> t Bool -> LogicOp t Bool
LogEquiv :: t Bool -> t Bool -> LogicOp t Bool
instance HFunctor LogicOp
instance HTraversable LogicOp where
htraverse f = \case
LogLit b -> pure $ LogLit b
LogNot x -> LogNot <$> f x
LogAnd x y -> LogAnd <$> f x <*> f y
LogOr x y -> LogOr <$> f x <*> f y
LogImpl x y -> LogImpl <$> f x <*> f y
LogEquiv x y -> LogEquiv <$> f x <*> f y
instance HFoldableAt Identity LogicOp where
hfoldMap = implHfoldMap $ \case
LogLit b -> pure b
LogNot x -> not <$> x
LogAnd x y -> liftA2 (&&) x y
LogOr x y -> liftA2 (||) x y
LogImpl x y -> liftA2 (||) (not <$> x) y
LogEquiv x y -> liftA2 (&&) (liftA2 (||) (not <$> x) y) (liftA2 (||) (not <$> y) x)
instance HFoldableAt SBV LogicOp where
hfoldMap = implHfoldMap $ \case
LogLit b -> fromBool b
LogNot x -> sNot x
LogAnd x y -> x .&& y
LogOr x y -> x .|| y
LogImpl x y -> x .=> y
LogEquiv x y -> x .<=> y
instance Pretty2 LogicOp where
prettys2Prec p = \case
LogLit True -> \r -> "T" ++ r
LogLit False -> \r -> "F" ++ r
LogNot x -> showParen (p > 8) $ showString "¬ " . prettys1Prec 9 x
LogAnd x y ->
showParen (p > 3) $ prettys1Prec 4 x . showString " ∧ " . prettys1Prec 4 y
LogOr x y ->
showParen (p > 2) $ prettys1Prec 3 x . showString " ∨ " . prettys1Prec 3 y
LogImpl x y ->
showParen (p > 1) $ prettys1Prec 2 x . showString " -> " . prettys1Prec 2 y
LogEquiv x y ->
showParen (p > 0) $ prettys1Prec 1 x . showString " <-> " . prettys1Prec 1 y