rerefined-0.1.0: src/Rerefined/Predicate/Logical.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
module Rerefined.Predicate.Logical where
import Rerefined.Predicate.Common
import Rerefined.Refined
import Rerefined.Refine.Unsafe
-- | Logical binary operator.
--
-- No need to disambiguate that these are binary operators, because there's only
-- one logical unary operator 'Not'.
data LogicOp = And | Or | Nand | Nor | Xor | Xnor
-- | A logical binary operation on two predicates.
data Logical (op :: LogicOp) l r
-- TODO could do whatever we want here e.g. infix. (but idk what e.g. XNOR uses)
instance (Predicate l, Predicate r, ReifyLogicOp op)
=> Predicate (Logical op l r) where
predicateName _ d = showParen (d > 10) $
showString "Logical "
. showString (reifyLogicOpPretty @op) . showChar ' '
. predicateName (proxy# @l) 11 . showChar ' '
. predicateName (proxy# @r) 11
instance (Refine l a, Refine r a, ReifyLogicOp op)
=> Refine (Logical op l r) a where
validate p a =
reifyLogicOp @op (validateFail p)
(validate (proxy# @l) a)
(validate (proxy# @r) a)
-- | Reify a logical binary operator type tag.
class ReifyLogicOp (op :: LogicOp) where
reifyLogicOpPretty :: String
reifyLogicOp
:: (String -> [a] -> Maybe a)
-> Maybe a
-> Maybe a
-> Maybe a
instance ReifyLogicOp And where
reifyLogicOpPretty = "And"
reifyLogicOp fFail l r =
case l of
Nothing ->
case r of
Nothing -> Nothing
Just er -> fFail "AND: right failed" [ er]
Just el ->
case r of
Nothing -> fFail "AND: left failed" [el ]
Just er -> fFail "AND: l&r failed" [el, er]
instance ReifyLogicOp Or where
reifyLogicOpPretty = "Or"
reifyLogicOp fFail l r =
case l of
Nothing -> Nothing
Just el ->
case r of
Nothing -> Nothing
Just er -> fFail "OR: l&r failed" [el, er]
instance ReifyLogicOp Nand where
reifyLogicOpPretty = "Nand"
reifyLogicOp fFail l r =
case l of
Just _ -> Nothing
Nothing ->
case r of
Just _ -> Nothing
Nothing -> fFail "NAND: l&r succeeded" [ ]
instance ReifyLogicOp Nor where
reifyLogicOpPretty = "Nor"
reifyLogicOp fFail l r =
case l of
Just el ->
case r of
Just _ -> Nothing
Nothing -> fFail "NOR: right succeeded" [el ]
Nothing ->
case r of
Just er -> fFail "NOR: left succeeded" [ er]
Nothing -> fFail "NOR: l&r succeeded" [ ]
instance ReifyLogicOp Xor where
reifyLogicOpPretty = "Xor"
reifyLogicOp fFail l r =
case l of
Nothing ->
case r of
Just _ -> Nothing
Nothing -> fFail "XOR: l&r succeeded" [ ]
Just el ->
case r of
Nothing -> Nothing
Just er -> fFail "XOR: l&r failed" [el, er]
instance ReifyLogicOp Xnor where
reifyLogicOpPretty = "Xnor"
reifyLogicOp fFail l r =
case l of
Nothing ->
case r of
Nothing -> Nothing
Just er -> fFail "XNOR: right failed" [ er]
Just el ->
case r of
Just _ -> Nothing
Nothing -> fFail "XNOR: left failed" [el ]
data Not p
instance Predicate p => Predicate (Not p) where
predicateName _ = predicateName1 @p "Not"
instance Refine p a => Refine (Not p) a where
validate p a =
case validate (proxy# @p) a of
Just _ -> Nothing
Nothing -> validateFail p "NOT: predicate succeeded" []
-- TODO principle of explosion? (p and not p -> anything)
-- TODO
rerefineDeMorgans1
:: Refined (Not (Logical Or l r)) a
-> Refined (Logical And (Not l) (Not r)) a
rerefineDeMorgans1 = unsafeRerefine
-- TODO
rerefineDeMorgans2
:: Refined (Not (Logical And l r)) a
-> Refined (Logical Or (Not l) (Not r)) a
rerefineDeMorgans2 = unsafeRerefine