fir-0.1.0.0: src/Math/Logic/Class.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-|
Module: Math.Logic.Class
This module overloads logical functionalities so that they can be used to manipulate ASTs:
* overloaded boolen operations such as @&&@, @||@, @xor@...
* overloaded if-then-else for use with @RebindableSyntax@,
* alternative @Eq@ and @Ord@ type classes which allow overloading with ASTs.
-}
module Math.Logic.Class where
-- base
import Prelude
( Int, Word, Foldable(..) )
import qualified Prelude
import Foreign.C.Types
import qualified GHC.Stack
( HasCallStack )
-- fir
import Deriving.Base
( Base(..) ) -- newtype for deriving via base instances
import FIR.Prelude
----------------------------------------------------------------------
infixr 3 &&
infixr 2 ||
class Boolean b where
true :: b
false :: b
(&&) :: b -> b -> b
(||) :: b -> b -> b
not :: b -> b
instance Boolean Bool where
true = True
false = False
(&&) = (Prelude.&&)
(||) = (Prelude.||)
not = Prelude.not
infix 4 ==
infix 4 /=
type family Choosing b (t :: (Type,Type,Type)) = r | r -> b t where
Choosing b '(x,y,z) = b -> x -> y -> z
class Boolean b => Choose b (t :: (Type,Type,Type)) where
choose :: Choosing b t
ifThenElse :: (GHC.Stack.HasCallStack, Choose b (t :: (Type,Type,Type)))
=> Choosing b t
ifThenElse = choose
instance (x ~ y, x ~ z) => Choose Bool '(x,y,z) where
choose True x _ = x
choose False _ y = y
class Boolean (Logic a) => Eq a where
type Logic a
(==) :: a -> a -> Logic a
(/=) :: a -> a -> Logic a
a /= b = not (a == b)
instance Prelude.Eq a => Eq (Base a) where
type Logic (Base a) = Bool
(==) = coerce ( (Prelude.==) :: a -> a -> Bool )
(/=) = coerce ( (Prelude./=) :: a -> a -> Bool )
deriving via Base () instance Eq ()
deriving via Base Bool instance Eq Bool
deriving via Base Word8 instance Eq Word8
deriving via Base Word16 instance Eq Word16
deriving via Base Word32 instance Eq Word32
deriving via Base Word64 instance Eq Word64
deriving via Base Word instance Eq Word
deriving via Base Int8 instance Eq Int8
deriving via Base Int16 instance Eq Int16
deriving via Base Int32 instance Eq Int32
deriving via Base Int64 instance Eq Int64
deriving via Base Int instance Eq Int
deriving via Base Half instance Eq Half
deriving via Base Float instance Eq Float
deriving via Base Double instance Eq Double
deriving via Base CChar instance Eq CChar
deriving via Base CSChar instance Eq CSChar
deriving via Base CUChar instance Eq CUChar
deriving via Base CShort instance Eq CShort
deriving via Base CUShort instance Eq CUShort
deriving via Base CInt instance Eq CInt
deriving via Base CUInt instance Eq CUInt
deriving via Base CLong instance Eq CLong
deriving via Base CULong instance Eq CULong
deriving via Base CLLong instance Eq CLLong
deriving via Base CULLong instance Eq CULLong
deriving via Base CFloat instance Eq CFloat
deriving via Base CDouble instance Eq CDouble
newtype All b = All { getAll :: b }
newtype Any b = Any { getAny :: b }
instance Boolean b => Semigroup (All b) where
(<>) = coerce ( (&&) @b )
instance Boolean b => Monoid (All b) where
mempty = coerce ( true @b )
instance Boolean b => Semigroup (Any b) where
(<>) = coerce ( (||) @b )
instance Boolean b => Monoid (Any b) where
mempty = coerce (false @b)
-- from Data.Functor.Utils
{-# INLINE (#.) #-}
(#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c)
(#.) _f = coerce
and :: (Foldable t, Boolean b) => t b -> b
and = getAll #. foldMap All
or :: (Foldable t, Boolean b) => t b -> b
or = getAny #. foldMap Any
any :: (Foldable t, Boolean b) => (a -> b) -> t a -> b
any p = getAny #. foldMap (Any #. p)
all :: (Foldable t, Boolean b) => (a -> b) -> t a -> b
all p = getAll #. foldMap (All #. p)
infix 4 <=
infix 4 <
infix 4 >=
infix 4 >
class Eq a => Ord a where
--type Ordering a
--compare :: a -> a -> Ordering a
(<=) :: a -> a -> Logic a
(>=) :: a -> a -> Logic a
(<) :: a -> a -> Logic a
(>) :: a -> a -> Logic a
max :: a -> a -> a
min :: a -> a -> a
(>=) = flip (<=)
(>) = flip (<)
instance Prelude.Ord a => Ord (Base a) where
(<=) = coerce ( (Prelude.<=) :: a -> a -> Bool )
(>=) = coerce ( (Prelude.>=) :: a -> a -> Bool )
(<) = coerce ( (Prelude.<) :: a -> a -> Bool )
(>) = coerce ( (Prelude.>) :: a -> a -> Bool )
max = coerce ( Prelude.max :: a -> a -> a )
min = coerce ( Prelude.min :: a -> a -> a )
deriving via Base () instance Ord ()
deriving via Base Bool instance Ord Bool
deriving via Base Word8 instance Ord Word8
deriving via Base Word16 instance Ord Word16
deriving via Base Word32 instance Ord Word32
deriving via Base Word64 instance Ord Word64
deriving via Base Word instance Ord Word
deriving via Base Int8 instance Ord Int8
deriving via Base Int16 instance Ord Int16
deriving via Base Int32 instance Ord Int32
deriving via Base Int64 instance Ord Int64
deriving via Base Int instance Ord Int
deriving via Base Half instance Ord Half
deriving via Base Float instance Ord Float
deriving via Base Double instance Ord Double
deriving via Base CChar instance Ord CChar
deriving via Base CSChar instance Ord CSChar
deriving via Base CUChar instance Ord CUChar
deriving via Base CShort instance Ord CShort
deriving via Base CUShort instance Ord CUShort
deriving via Base CInt instance Ord CInt
deriving via Base CUInt instance Ord CUInt
deriving via Base CLong instance Ord CLong
deriving via Base CULong instance Ord CULong
deriving via Base CLLong instance Ord CLLong
deriving via Base CULLong instance Ord CULLong
deriving via Base CFloat instance Ord CFloat
deriving via Base CDouble instance Ord CDouble