{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Algebra.Boolean
( BooleanAlgebra
, (==>)
, neg
-- * Adjunction between Boolean and Heyting algebras
, Boolean
, runBooleanAlgebra
, boolean
) where
import Control.Applicative (Const (..))
import Data.Data (Data, Typeable)
import Data.Functor.Identity (Identity (..))
import Data.Proxy (Proxy (..))
import Data.Semigroup ( All (..)
, Any (..)
, Endo (..)
)
import Data.Tagged (Tagged (..))
import GHC.Generics (Generic)
import Algebra.Heyting
import Algebra.Lattice ( Lattice
, BoundedJoinSemiLattice
, BoundedMeetSemiLattice
)
class Heyting a => Boolean a
instance Boolean Bool
instance Boolean All
instance Boolean Any
instance Boolean ()
instance Boolean (Proxy a)
instance Boolean a => Boolean (Tagged t a)
instance Boolean b => Boolean (a -> b)
#if MIN_VERSION_base(4,8,0)
instance Boolean a => Boolean (Identity a)
#endif
instance Boolean a => Boolean (Const a b)
instance Boolean a => Boolean (Endo a)
-- | Every Heyting algebra contains a Boolean algebra. @'toBoolean'@ maps onto
-- it; moreover it is a monad (Heyting algebra is a category as every poset is)
-- which preserves finite infima.
--
toBoolean :: Heyting a => a -> a
toBoolean = neg . neg
-- |
-- @'Boolean'@ is the left adjoint functor from the category of Heyting algebras
-- to the category of Boolean algebras; its right adjoint is the inclusion.
newtype BooleanAlgebra a = BooleanAlgebra
{ runBooleanAlgebra :: a -- ^ extract value from @'Boolean'@
}
deriving
( BoundedJoinSemiLattice
, BoundedMeetSemiLattice
, Lattice
, Heyting
, Eq, Ord, Read, Show, Bounded, Typeable, Data, Generic
)
instance Heyting a => Boolean (BooleanAlgebra a)
-- |
-- Smart constructro of the @'Boolean'@ type.
boolean :: Heyting a => a -> BooleanAlgebra a
boolean = BooleanAlgebra . toBoolean