{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
module PredicateTransformers where
import Control.Applicative
import Control.DeepSeq (NFData, force)
import Control.Exception
import Control.Lens hiding (index)
import Control.Monad
import Control.Monad.Writer (execWriter, tell)
import Data.Bool
import Data.Foldable (toList)
import Data.Functor.Rep (Representable (..))
import Data.Semigroup (All (..), Any (..))
import Data.Typeable
import Debug.Trace
import System.IO.Unsafe
import Control.Concurrent (myThreadId, throwTo)
import Control.Exception (SomeAsyncException)
class Predicatory a where
otherHand :: a -> a -> a
also :: a -> a -> a
stop :: a
continue :: a
instance Predicatory a => Predicatory (e -> a) where
(e -> a
f otherHand :: (e -> a) -> (e -> a) -> e -> a
`otherHand` e -> a
f') e
e = e -> a
f e
e a -> a -> a
forall a. Predicatory a => a -> a -> a
`otherHand` e -> a
f' e
e
(e -> a
f also :: (e -> a) -> (e -> a) -> e -> a
`also` e -> a
f') e
e = e -> a
f e
e a -> a -> a
forall a. Predicatory a => a -> a -> a
`also` e -> a
f' e
e
stop :: e -> a
stop = \e
_ -> a
forall a. Predicatory a => a
stop
continue :: e -> a
continue = \e
_ -> a
forall a. Predicatory a => a
continue
infixr 3 `also`
infixr 2 `otherHand`
class Exceptional a where
assess :: a -> IO ()
data PredicateFailed = PredicateFailed
deriving (Int -> PredicateFailed -> ShowS
[PredicateFailed] -> ShowS
PredicateFailed -> String
(Int -> PredicateFailed -> ShowS)
-> (PredicateFailed -> String)
-> ([PredicateFailed] -> ShowS)
-> Show PredicateFailed
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PredicateFailed -> ShowS
showsPrec :: Int -> PredicateFailed -> ShowS
$cshow :: PredicateFailed -> String
show :: PredicateFailed -> String
$cshowList :: [PredicateFailed] -> ShowS
showList :: [PredicateFailed] -> ShowS
Show, Typeable)
instance Exception PredicateFailed
instance Predicatory Bool where
otherHand :: Bool -> Bool -> Bool
otherHand = Bool -> Bool -> Bool
(||)
also :: Bool -> Bool -> Bool
also = Bool -> Bool -> Bool
(&&)
stop :: Bool
stop = Bool
False
continue :: Bool
continue = Bool
True
instance Exceptional Bool where
assess :: Bool -> IO ()
assess Bool
b = do
Bool -> IO Bool
forall a. a -> IO a
evaluate Bool
b
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
b IO ()
forall a. Predicatory a => a
stop
instance Predicatory (IO ()) where
otherHand :: IO () -> IO () -> IO ()
otherHand IO ()
x IO ()
y = do
IO () -> [Handler ()] -> IO ()
forall a. IO a -> [Handler a] -> IO a
catches IO ()
x
[ (SomeAsyncException -> IO ()) -> Handler ()
forall a e. Exception e => (e -> IO a) -> Handler a
Handler ((SomeAsyncException -> IO ()) -> Handler ())
-> (SomeAsyncException -> IO ()) -> Handler ()
forall a b. (a -> b) -> a -> b
$ \(SomeAsyncException
ex :: SomeAsyncException) -> do
ThreadId
tid <- IO ThreadId
myThreadId
ThreadId -> SomeAsyncException -> IO ()
forall e. Exception e => ThreadId -> e -> IO ()
throwTo ThreadId
tid SomeAsyncException
ex
, (SomeException -> IO ()) -> Handler ()
forall a e. Exception e => (e -> IO a) -> Handler a
Handler ((SomeException -> IO ()) -> Handler ())
-> (SomeException -> IO ()) -> Handler ()
forall a b. (a -> b) -> a -> b
$ \(SomeException
_ex :: SomeException) -> IO ()
y
]
also :: IO () -> IO () -> IO ()
also = IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>)
stop :: IO ()
stop = PredicateFailed -> IO ()
forall e a. Exception e => e -> IO a
throwIO PredicateFailed
PredicateFailed
continue :: IO ()
continue = () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
instance Exceptional (IO ()) where
assess :: IO () -> IO ()
assess IO ()
x = IO ()
x IO () -> (() -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= () -> IO ()
forall a. a -> IO a
evaluate
type Pred a = a -> Bool
type PT p a b = (a -> p) -> (b -> p)
just :: Predicatory p => PT p a (Maybe a)
just :: forall p a. Predicatory p => PT p a (Maybe a)
just = Fold (Maybe a) a -> PT p a (Maybe a)
forall p s a. Predicatory p => Fold s a -> PT p a s
allOf1 (a -> f a) -> Maybe a -> f (Maybe a)
forall a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Maybe a) (f (Maybe b))
Fold (Maybe a) a
_Just
left :: Predicatory p => PT p e (Either e a)
left :: forall p e a. Predicatory p => PT p e (Either e a)
left = Fold (Either e a) e -> PT p e (Either e a)
forall p s a. Predicatory p => Fold s a -> PT p a s
allOf1 (e -> f e) -> Either e a -> f (Either e a)
forall a c b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Either a c) (f (Either b c))
Fold (Either e a) e
_Left
right :: Predicatory p => PT p a (Either e a)
right :: forall p a e. Predicatory p => PT p a (Either e a)
right = Fold (Either e a) a -> PT p a (Either e a)
forall p s a. Predicatory p => Fold s a -> PT p a s
allOf1 (a -> f a) -> Either e a -> f (Either e a)
forall c a b (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p a (f b) -> p (Either c a) (f (Either c b))
Fold (Either e a) a
_Right
endingWith :: (Predicatory p, Foldable f) => PT p a (f a)
endingWith :: forall p (f :: * -> *) a.
(Predicatory p, Foldable f) =>
PT p a (f a)
endingWith a -> p
_ (f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> []) = p
forall a. Predicatory a => a
stop
endingWith a -> p
p (f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [a]
xs) = a -> p
p (a -> p) -> a -> p
forall a b. (a -> b) -> a -> b
$ [a] -> a
forall a. HasCallStack => [a] -> a
last [a]
xs
{-# INLINEABLE endingWith #-}
startingWith :: (Predicatory p, Foldable f) => PT p a (f a)
startingWith :: forall p (f :: * -> *) a.
(Predicatory p, Foldable f) =>
PT p a (f a)
startingWith a -> p
p (f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> (a
x : [a]
_)) = a -> p
p a
x
startingWith a -> p
_ (f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> []) = p
forall a. Predicatory a => a
stop
{-# INLINEABLE startingWith #-}
onlyContains :: (Predicatory p, Foldable f) => PT p a (f a)
onlyContains :: forall p (f :: * -> *) a.
(Predicatory p, Foldable f) =>
PT p a (f a)
onlyContains a -> p
p (f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList -> [a
x]) = a -> p
p a
x
onlyContains a -> p
_ f a
_ = p
forall a. Predicatory a => a
stop
{-# INLINEABLE onlyContains #-}
kth :: (Predicatory p, Foldable f) => Int -> PT p a (f a)
kth :: forall p (f :: * -> *) a.
(Predicatory p, Foldable f) =>
Int -> PT p a (f a)
kth Int
k a -> p
p = PT p a [a]
forall p (f :: * -> *) a.
(Predicatory p, Foldable f) =>
PT p a (f a)
startingWith a -> p
p ([a] -> p) -> (f a -> [a]) -> f a -> p
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
k ([a] -> [a]) -> (f a -> [a]) -> f a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList
{-# INLINEABLE kth #-}
list :: Predicatory p => [a -> p] -> [a] -> p
list :: forall p a. Predicatory p => [a -> p] -> [a] -> p
list (a -> p
p : [a -> p]
ps) (a
x : [a]
xs) = a -> p
p a
x p -> p -> p
forall a. Predicatory a => a -> a -> a
`also` [a -> p] -> [a] -> p
forall p a. Predicatory p => [a -> p] -> [a] -> p
list [a -> p]
ps [a]
xs
list [] [] = p
forall a. Predicatory a => a
continue
list [a -> p]
_ [a]
_ = p
forall a. Predicatory a => a
stop
dist ::
(Predicatory p, Eq (f ()), Functor f, Foldable f) =>
f (a -> p) ->
f a ->
p
dist :: forall p (f :: * -> *) a.
(Predicatory p, Eq (f ()), Functor f, Foldable f) =>
f (a -> p) -> f a -> p
dist f (a -> p)
preds f a
values =
p -> p -> Bool -> p
forall a. a -> a -> Bool -> a
bool p
forall a. Predicatory a => a
stop p
forall a. Predicatory a => a
continue ((() () -> f (a -> p) -> f ()
forall a b. a -> f b -> f a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f (a -> p)
preds) f () -> f () -> Bool
forall a. Eq a => a -> a -> Bool
== (() () -> f a -> f ()
forall a b. a -> f b -> f a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f a
values))
p -> p -> p
forall a. Predicatory a => a -> a -> a
`also` [a -> p] -> [a] -> p
forall p a. Predicatory p => [a -> p] -> [a] -> p
list (f (a -> p) -> [a -> p]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList f (a -> p)
preds) (f a -> [a]
forall a. f a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList f a
values)
{-# INLINEABLE dist #-}
distRep ::
Representable f =>
f (a -> p) ->
f a ->
f p
distRep :: forall (f :: * -> *) a p.
Representable f =>
f (a -> p) -> f a -> f p
distRep f (a -> p)
pr f a
fa = (Rep f -> p) -> f p
forall a. (Rep f -> a) -> f a
forall (f :: * -> *) a. Representable f => (Rep f -> a) -> f a
tabulate (\Rep f
r -> f (a -> p) -> Rep f -> a -> p
forall a. f a -> Rep f -> a
forall (f :: * -> *) a. Representable f => f a -> Rep f -> a
index f (a -> p)
pr Rep f
r (a -> p) -> a -> p
forall a b. (a -> b) -> a -> b
$ f a -> Rep f -> a
forall a. f a -> Rep f -> a
forall (f :: * -> *) a. Representable f => f a -> Rep f -> a
index f a
fa Rep f
r)
{-# INLINEABLE distRep #-}
allTrue :: (Predicatory p, Foldable f) => f (a -> p) -> a -> p
allTrue :: forall p (f :: * -> *) a.
(Predicatory p, Foldable f) =>
f (a -> p) -> a -> p
allTrue f (a -> p)
ps a
a = ((a -> p) -> p -> p) -> p -> f (a -> p) -> p
forall a b. (a -> b -> b) -> b -> f a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a -> p
p p
r -> a -> p
p a
a p -> p -> p
forall a. Predicatory a => a -> a -> a
`also` p
r) p
forall a. Predicatory a => a
continue f (a -> p)
ps
allOf1 :: Predicatory p => Fold s a -> PT p a s
allOf1 :: forall p s a. Predicatory p => Fold s a -> PT p a s
allOf1 Fold s a
g a -> p
p s
vs =
p -> p -> Bool -> p
forall a. a -> a -> Bool -> a
bool p
forall a. Predicatory a => a
stop p
forall a. Predicatory a => a
continue (Getting Any s a -> s -> Bool
forall s a. Getting Any s a -> s -> Bool
notNullOf Getting Any s a
Fold s a
g s
vs)
p -> p -> p
forall a. Predicatory a => a -> a -> a
`also` Getting (Endo p) s a -> (a -> p -> p) -> p -> s -> p
forall r s a. Getting (Endo r) s a -> (a -> r -> r) -> r -> s -> r
foldrOf Getting (Endo p) s a
Fold s a
g (\a
x p
r -> a -> p
p a
x p -> p -> p
forall a. Predicatory a => a -> a -> a
`also` p
r) p
forall a. Predicatory a => a
continue s
vs
pattern a $m:=> :: forall {r} {a} {b}. (a, b) -> (a -> b -> r) -> ((# #) -> r) -> r
$b:=> :: forall {a} {b}. a -> b -> (a, b)
:=> b = (a, b)
pair :: Predicatory p => (a -> p) -> (b -> p) -> (a, b) -> p
pair :: forall p a b. Predicatory p => (a -> p) -> (b -> p) -> (a, b) -> p
pair a -> p
f b -> p
s (a
a, b
b) = a -> p
f a
a p -> p -> p
forall a. Predicatory a => a -> a -> a
`also` b -> p
s b
b
(!) :: (b -> a) -> (a -> c) -> b -> c
! :: forall b a c. (b -> a) -> (a -> c) -> b -> c
(!) = ((a -> c) -> (b -> a) -> b -> c) -> (b -> a) -> (a -> c) -> b -> c
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> c) -> (b -> a) -> b -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
(.)
infixr 9 !
traced :: Show a => (a -> c) -> a -> c
traced :: forall a c. Show a => (a -> c) -> a -> c
traced a -> c
p a
a = a -> c -> c
forall a b. Show a => a -> b -> b
traceShow a
a (a -> c
p a
a)
traceFail :: (Predicatory p, Exceptional p) => (a -> String) -> PT p a a
traceFail :: forall p a.
(Predicatory p, Exceptional p) =>
(a -> String) -> PT p a a
traceFail a -> String
s a -> p
p a
a = IO p -> p
forall a. IO a -> a
unsafePerformIO (IO p -> p) -> IO p -> p
forall a b. (a -> b) -> a -> b
$ do
IO () -> IO (Either SomeException ())
forall e a. Exception e => IO a -> IO (Either e a)
try (p -> IO ()
forall a. Exceptional a => a -> IO ()
assess (a -> p
p a
a)) IO (Either SomeException ())
-> (Either SomeException () -> IO p) -> IO p
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
ex -> do
String -> IO ()
traceIO (a -> String
s a
a)
SomeException -> IO p
forall e a. Exception e => e -> IO a
throwIO (SomeException
ex :: SomeException)
Right () ->
p -> IO p
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure p
forall a. Predicatory a => a
continue
traceFailShow :: (Exceptional p, Predicatory p, Show a) => PT p a a
traceFailShow :: forall p a. (Exceptional p, Predicatory p, Show a) => PT p a a
traceFailShow = (a -> String) -> PT p a a
forall p a.
(Predicatory p, Exceptional p) =>
(a -> String) -> PT p a a
traceFail a -> String
forall a. Show a => a -> String
show
traceFailFun :: (Predicatory p, Exceptional p) => (e -> a -> String) -> PT (e -> p) a a
traceFailFun :: forall p e a.
(Predicatory p, Exceptional p) =>
(e -> a -> String) -> PT (e -> p) a a
traceFailFun e -> a -> String
s a -> e -> p
p a
a e
e = IO p -> p
forall a. IO a -> a
unsafePerformIO (IO p -> p) -> IO p -> p
forall a b. (a -> b) -> a -> b
$ do
IO () -> IO (Either SomeException ())
forall e a. Exception e => IO a -> IO (Either e a)
try (p -> IO ()
forall a. Exceptional a => a -> IO ()
assess (a -> e -> p
p a
a e
e)) IO (Either SomeException ())
-> (Either SomeException () -> IO p) -> IO p
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
ex -> do
String -> IO ()
traceIO (e -> a -> String
s e
e a
a)
SomeException -> IO p
forall e a. Exception e => e -> IO a
throwIO (SomeException
ex :: SomeException)
Right () ->
p -> IO p
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure p
forall a. Predicatory a => a
continue
something :: Predicatory p => a -> p
something :: forall a e. Predicatory a => e -> a
something = p -> a -> p
forall a b. a -> b -> a
const p
forall a. Predicatory a => a
continue
forced :: (Predicatory p, NFData a) => a -> p
forced :: forall p a. (Predicatory p, NFData a) => a -> p
forced a
a = a -> a
forall a. NFData a => a -> a
force a
a a -> p -> p
forall a b. a -> b -> b
`seq` p
forall a. Predicatory a => a
continue
equals :: (Predicatory p, Eq a) => a -> a -> p
equals :: forall p a. (Predicatory p, Eq a) => a -> a -> p
equals a
a a
a' = p -> p -> Bool -> p
forall a. a -> a -> Bool -> a
bool p
forall a. Predicatory a => a
stop p
forall a. Predicatory a => a
continue (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a')