packages feed

heyting-algebras-0.2.0.1: src/Algebra/Heyting/Layered.hs

module Algebra.Heyting.Layered
  ( Layered (..)
  , layer
  ) where

import           Prelude

import           Algebra.Lattice ( BoundedJoinSemiLattice (..)
                                 , BoundedMeetSemiLattice (..)
                                 , Lattice (..)
                                 )

import           Algebra.Heyting ( Heyting (..) )

-- |
-- Layer one Heyting algebra on top of the other.  Note: this is not
-- a categorical sum.
data Layered a b
  = Lower a
  | Upper b
  deriving (Show, Eq, Ord)

instance ( Lattice a
         , Lattice b
         ) => Lattice (Layered a b) where
  l@Lower{} /\ Upper _   = l
  Upper _   /\ l@Lower{} = l
  Lower l   /\ Lower l'  = Lower $ l /\ l'
  Upper u   /\ Upper u'  = Upper $ u /\ u'

  Lower _   \/ u@Upper{} = u
  u@Upper{} \/ Lower _   = u
  Lower l   \/ Lower l'  = Lower $ l \/ l'
  Upper u   \/ Upper u'  = Upper $ u \/ u'

instance (BoundedJoinSemiLattice a, Lattice b) => BoundedJoinSemiLattice (Layered a b) where
  bottom = Lower bottom

instance (Lattice a, BoundedMeetSemiLattice b) => BoundedMeetSemiLattice (Layered a b) where
  top = Upper top

instance ( Heyting a
         , Heyting b
         , Eq a
         ) => Heyting (Layered a b) where
  Lower _   ==> Upper _      = Upper top
  Upper _   ==> l@Lower{}    = l
  Upper u   ==> Upper u'     = Upper $ u ==> u'
  Lower l   ==> Lower l'     = case l ==> l' of
    ll' | ll' == top -> Upper top
        | otherwise  -> Lower ll'

layer :: (a -> c) -> (b -> c) -> Layered a b -> c
layer f _ (Lower a) = f a
layer _ g (Upper b) = g b