kleene-0: src/Kleene/Equiv.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE UndecidableInstances #-}
module Kleene.Equiv where
import Prelude ()
import Prelude.Compat
import Algebra.Lattice
(BoundedJoinSemiLattice (..), JoinSemiLattice (..), joinLeq)
import Algebra.PartialOrd (PartialOrd (..))
import Kleene.Classes
import Kleene.Internal.Pretty
-- | Regular-expressions for which '==' is 'equivalent'.
--
-- >>> let re1 = star "a" <> "a" :: RE Char
-- >>> let re2 = "a" <> star "a" :: RE Char
--
-- >>> re1 == re2
-- False
--
-- >>> Equiv re1 == Equiv re2
-- True
--
-- 'Equiv' is also a 'PartialOrd' (but not 'Ord'!)
--
-- >>> Equiv "a" `leq` Equiv (star "a" :: RE Char)
-- True
--
-- Not all regular expessions are 'comparable':
--
-- >>> let reA = Equiv "a" :: Equiv RE Char
-- >>> let reB = Equiv "b" :: Equiv RE Char
-- >>> (leq reA reB, leq reB reA)
-- (False,False)
--
newtype Equiv r c = Equiv (r c)
deriving (Show, Semigroup, Monoid, BoundedJoinSemiLattice, JoinSemiLattice, Pretty)
instance Equivalent c (r c) => Eq (Equiv r c) where
(==) = equivalent
-- | \(a \preceq b := a \lor b = b \)
instance (JoinSemiLattice (r c), Equivalent c (r c)) => PartialOrd (Equiv r c) where
leq = joinLeq
deriving instance Kleene c (r c) => Kleene c (Equiv r c)
deriving instance Derivate c (r c) => Derivate c (Equiv r c)
deriving instance Match c (r c) => Match c (Equiv r c)
deriving instance Equivalent c (r c) => Equivalent c (Equiv r c)
deriving instance Complement c (r c) => Complement c (Equiv r c)
-- $setup
-- >>> import Kleene.RE (RE)