{-# OPTIONS_GHC -Wno-orphans #-}
{-# LANGUAGE DeriveGeneric #-}
{-|
    Module      :  AERN2.Kleenean
    Description :  Three-valued logic
    Copyright   :  (c) Michal Konecny
    License     :  BSD3

    Maintainer  :  mikkonecny@gmail.com
    Stability   :  experimental
    Portability :  portable

-}
module AERN2.Kleenean
(
    Kleenean(..), kleenean, tKleenean
)
where

import Numeric.MixedTypes.PreludeHiding
import qualified Prelude as P

-- import Test.SmallCheck.Series
import GHC.Generics

import Numeric.MixedTypes.Literals
    ( ConvertibleExactly(..), convertExactly, T(T) )
import Numeric.MixedTypes.Bool
    ( (&&),
      not,
      CanAndOrAsymmetric(..),
      CanNeg(negate),
      CanTestCertainly(..),
      and )

tKleenean :: T Kleenean
tKleenean :: T Kleenean
tKleenean = String -> T Kleenean
forall t. String -> T t
T String
"Kleenean"

data Kleenean = CertainTrue | CertainFalse | TrueOrFalse
  deriving (Kleenean -> Kleenean -> Bool
(Kleenean -> Kleenean -> Bool)
-> (Kleenean -> Kleenean -> Bool) -> Eq Kleenean
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Kleenean -> Kleenean -> Bool
$c/= :: Kleenean -> Kleenean -> Bool
== :: Kleenean -> Kleenean -> Bool
$c== :: Kleenean -> Kleenean -> Bool
P.Eq, Int -> Kleenean -> ShowS
[Kleenean] -> ShowS
Kleenean -> String
(Int -> Kleenean -> ShowS)
-> (Kleenean -> String) -> ([Kleenean] -> ShowS) -> Show Kleenean
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Kleenean] -> ShowS
$cshowList :: [Kleenean] -> ShowS
show :: Kleenean -> String
$cshow :: Kleenean -> String
showsPrec :: Int -> Kleenean -> ShowS
$cshowsPrec :: Int -> Kleenean -> ShowS
Show, (forall x. Kleenean -> Rep Kleenean x)
-> (forall x. Rep Kleenean x -> Kleenean) -> Generic Kleenean
forall x. Rep Kleenean x -> Kleenean
forall x. Kleenean -> Rep Kleenean x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Kleenean x -> Kleenean
$cfrom :: forall x. Kleenean -> Rep Kleenean x
Generic)

-- instance Serial IO Kleenean

type CanBeKleenean t = ConvertibleExactly t Kleenean
kleenean :: (CanBeKleenean t) => t -> Kleenean
kleenean :: t -> Kleenean
kleenean = t -> Kleenean
forall t1 t2. ConvertibleExactly t1 t2 => t1 -> t2
convertExactly

instance ConvertibleExactly Kleenean Kleenean where
  safeConvertExactly :: Kleenean -> ConvertResult Kleenean
safeConvertExactly = Kleenean -> ConvertResult Kleenean
forall a b. b -> Either a b
Right

instance ConvertibleExactly Bool Kleenean where
  safeConvertExactly :: Bool -> ConvertResult Kleenean
safeConvertExactly Bool
True = Kleenean -> ConvertResult Kleenean
forall a b. b -> Either a b
Right Kleenean
CertainTrue
  safeConvertExactly Bool
False = Kleenean -> ConvertResult Kleenean
forall a b. b -> Either a b
Right Kleenean
CertainFalse

instance CanTestCertainly Kleenean where
  isCertainlyTrue :: Kleenean -> Bool
isCertainlyTrue = (Kleenean -> Kleenean -> Bool
forall a. Eq a => a -> a -> Bool
P.== Kleenean
CertainTrue)
  isCertainlyFalse :: Kleenean -> Bool
isCertainlyFalse = (Kleenean -> Kleenean -> Bool
forall a. Eq a => a -> a -> Bool
P.== Kleenean
CertainFalse)

instance CanNeg Kleenean where
  negate :: Kleenean -> NegType Kleenean
negate Kleenean
CertainTrue = NegType Kleenean
Kleenean
CertainFalse
  negate Kleenean
CertainFalse = NegType Kleenean
Kleenean
CertainTrue
  negate Kleenean
TrueOrFalse = NegType Kleenean
Kleenean
TrueOrFalse

_testNeg1 :: Kleenean
_testNeg1 :: Kleenean
_testNeg1 = Kleenean -> NegType Kleenean
forall t. CanNeg t => t -> NegType t
not Kleenean
CertainTrue

instance CanAndOrAsymmetric Kleenean Kleenean
  where
  type AndOrType Kleenean Kleenean = Kleenean
  and2 :: Kleenean -> Kleenean -> AndOrType Kleenean Kleenean
and2 Kleenean
CertainTrue Kleenean
CertainTrue = AndOrType Kleenean Kleenean
Kleenean
CertainTrue
  and2 Kleenean
CertainFalse Kleenean
_ = AndOrType Kleenean Kleenean
Kleenean
CertainFalse
  and2 Kleenean
_ Kleenean
CertainFalse = AndOrType Kleenean Kleenean
Kleenean
CertainFalse
  and2 Kleenean
_ Kleenean
_ = AndOrType Kleenean Kleenean
Kleenean
TrueOrFalse
  or2 :: Kleenean -> Kleenean -> AndOrType Kleenean Kleenean
or2 Kleenean
CertainFalse Kleenean
CertainFalse = AndOrType Kleenean Kleenean
Kleenean
CertainFalse
  or2 Kleenean
CertainTrue Kleenean
_ = AndOrType Kleenean Kleenean
Kleenean
CertainTrue
  or2 Kleenean
_ Kleenean
CertainTrue = AndOrType Kleenean Kleenean
Kleenean
CertainTrue
  or2 Kleenean
_ Kleenean
_ = AndOrType Kleenean Kleenean
Kleenean
TrueOrFalse

instance CanAndOrAsymmetric Bool Kleenean
  where
  type AndOrType Bool Kleenean = Kleenean
  and2 :: Bool -> Kleenean -> AndOrType Bool Kleenean
and2 Bool
b = Kleenean -> Kleenean -> AndOrType Kleenean Kleenean
forall t1 t2.
CanAndOrAsymmetric t1 t2 =>
t1 -> t2 -> AndOrType t1 t2
and2 (Bool -> Kleenean
forall t. CanBeKleenean t => t -> Kleenean
kleenean Bool
b)
  or2 :: Bool -> Kleenean -> AndOrType Bool Kleenean
or2 Bool
b = Kleenean -> Kleenean -> AndOrType Kleenean Kleenean
forall t1 t2.
CanAndOrAsymmetric t1 t2 =>
t1 -> t2 -> AndOrType t1 t2
or2 (Bool -> Kleenean
forall t. CanBeKleenean t => t -> Kleenean
kleenean Bool
b)

instance CanAndOrAsymmetric Kleenean Bool
  where
  type AndOrType Kleenean Bool = Kleenean
  and2 :: Kleenean -> Bool -> AndOrType Kleenean Bool
and2 Kleenean
k Bool
b = Kleenean -> Kleenean -> AndOrType Kleenean Kleenean
forall t1 t2.
CanAndOrAsymmetric t1 t2 =>
t1 -> t2 -> AndOrType t1 t2
and2 Kleenean
k (Bool -> Kleenean
forall t. CanBeKleenean t => t -> Kleenean
kleenean Bool
b)
  or2 :: Kleenean -> Bool -> AndOrType Kleenean Bool
or2 Kleenean
k Bool
b = Kleenean -> Kleenean -> AndOrType Kleenean Kleenean
forall t1 t2.
CanAndOrAsymmetric t1 t2 =>
t1 -> t2 -> AndOrType t1 t2
or2 Kleenean
k (Bool -> Kleenean
forall t. CanBeKleenean t => t -> Kleenean
kleenean Bool
b)

_testAndOr1 :: Kleenean
_testAndOr1 :: Kleenean
_testAndOr1 = Kleenean
TrueOrFalse Kleenean -> Bool -> AndOrType Kleenean Bool
forall t1 t2.
CanAndOrAsymmetric t1 t2 =>
t1 -> t2 -> AndOrType t1 t2
&& Bool
False

_testAndOr2 :: Kleenean
_testAndOr2 :: Kleenean
_testAndOr2 = [Kleenean] -> Kleenean
forall t. (CanAndOrSameType t, CanTestCertainly t) => [t] -> t
and [Kleenean
CertainTrue, Kleenean
TrueOrFalse, Kleenean
CertainFalse]