-- |
-- Copyright  : (c) Ivan Perez, 2017-2022
-- License    : BSD-style (see the LICENSE file in the distribution)
-- Maintainer : ivan.perez@keera.co.uk
--
-- Past-time Linear Temporal Logics based on SFs.
--
-- This module contains a definition of ptLTL with prev/last on top of Signal
-- Functions.
--
-- The difference between the future time and the past time LTL is that the
-- former needs a trace for evaluation, and the latter can be embedded into a
-- signal function network without additional support for evaluation.
module FRP.Yampa.LTLPast where

-- External imports
import FRP.Yampa (Event (..), SF, arr, iPre, loopPre, switch, (>>>))

-- | True if both inputs are True.
andSF :: SF (Bool, Bool) Bool
andSF :: SF (Bool, Bool) Bool
andSF = forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Bool -> Bool -> Bool
(&&))

-- | True if either or both inputs are True.
orSF :: SF (Bool, Bool) Bool
orSF :: SF (Bool, Bool) Bool
orSF = forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Bool -> Bool -> Bool
(||))

-- | True if the input signal is False.
notSF :: SF Bool Bool
notSF :: SF Bool Bool
notSF = forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr Bool -> Bool
not

-- | True if the first signal is False or the second one is True.
impliesSF :: SF (Bool, Bool) Bool
impliesSF :: SF (Bool, Bool) Bool
impliesSF = forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr forall a b. (a -> b) -> a -> b
$ \(Bool
i, Bool
p) -> Bool -> Bool
not Bool
i Bool -> Bool -> Bool
|| Bool
p

-- | True a a time if the input signal has been always True so far.
sofarSF :: SF Bool Bool
sofarSF :: SF Bool Bool
sofarSF = forall c a b. c -> SF (a, c) (b, c) -> SF a b
loopPre Bool
True forall a b. (a -> b) -> a -> b
$ forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr forall a b. (a -> b) -> a -> b
$ \(Bool
n, Bool
o) -> let n' :: Bool
n' = Bool
o Bool -> Bool -> Bool
&& Bool
n in (Bool
n', Bool
n')

-- | True at a time if the input signal has ever been True before.
everSF :: SF Bool Bool
everSF :: SF Bool Bool
everSF = forall c a b. c -> SF (a, c) (b, c) -> SF a b
loopPre Bool
False forall a b. (a -> b) -> a -> b
$ forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr forall a b. (a -> b) -> a -> b
$ \(Bool
n, Bool
o) -> let n' :: Bool
n' = Bool
o Bool -> Bool -> Bool
|| Bool
n in (Bool
n', Bool
n')

-- | True if the signal was True in the last sample. False at time zero.
lastSF :: SF Bool Bool
lastSF :: SF Bool Bool
lastSF = forall a. a -> SF a a
iPre Bool
False

-- | Weak Until. True if the first signal is True until the second becomes
-- True, if ever.
untilSF :: SF (Bool, Bool) Bool
untilSF :: SF (Bool, Bool) Bool
untilSF = forall a b c. SF a (b, Event c) -> (c -> SF a b) -> SF a b
switch
  (forall c a b. c -> SF (a, c) (b, c) -> SF a b
loopPre Bool
True forall a b. (a -> b) -> a -> b
$ forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr (\((Bool
i, Bool
u), Bool
o) ->
     let n :: Bool
n = Bool
o Bool -> Bool -> Bool
&& Bool
i
     in ((Bool
n, if Bool
o Bool -> Bool -> Bool
&& Bool
u then forall a. a -> Event a
Event () else forall a. Event a
NoEvent), Bool
n)))
  (\()
_ -> forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr forall a b. (a, b) -> b
snd forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> SF Bool Bool
sofarSF)