module Cooked.Tweak.Common
( runTweak,
runTweakFrom,
runTweakInChain,
runTweakInChain',
Tweak,
UntypedTweak (..),
MonadTweak (..),
failingTweak,
doNothingTweak,
viewTweak,
viewAllTweak,
setTweak,
overTweak,
overMaybeTweak,
overMaybeSelectingTweak,
selectP,
combineModsTweak,
iviewTweak,
ensureFailingTweak,
)
where
import Control.Arrow (second)
import Control.Monad
import Control.Monad.State
import Cooked.InitialDistribution
import Cooked.MockChain.BlockChain
import Cooked.MockChain.Direct
import Cooked.Skeleton
import Data.Default
import Data.Either.Combinators (rightToMaybe)
import Data.List (mapAccumL)
import Data.Maybe
import ListT (ListT)
import ListT qualified
import Optics.Core
class (MonadPlus m, MonadBlockChainWithoutValidation m) => MonadTweak m where
getTxSkel :: m TxSkel
putTxSkel :: TxSkel -> m ()
type Tweak m = StateT TxSkel (ListT m)
instance (MonadBlockChainWithoutValidation m) => MonadTweak (Tweak m) where
getTxSkel :: Tweak m TxSkel
getTxSkel = Tweak m TxSkel
forall s (m :: * -> *). MonadState s m => m s
get
putTxSkel :: TxSkel -> Tweak m ()
putTxSkel = TxSkel -> Tweak m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put
runTweakInChain :: (MonadPlus m) => Tweak m a -> TxSkel -> m (a, TxSkel)
runTweakInChain :: forall (m :: * -> *) a.
MonadPlus m =>
Tweak m a -> TxSkel -> m (a, TxSkel)
runTweakInChain Tweak m a
tweak = ListT m (a, TxSkel) -> m (a, TxSkel)
forall (m :: * -> *) a.
(Alternative m, Monad m) =>
ListT m a -> m a
ListT.alternate (ListT m (a, TxSkel) -> m (a, TxSkel))
-> (TxSkel -> ListT m (a, TxSkel)) -> TxSkel -> m (a, TxSkel)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tweak m a -> TxSkel -> ListT m (a, TxSkel)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT Tweak m a
tweak
runTweakInChain' :: (MonadPlus m) => Tweak m a -> TxSkel -> m [(a, TxSkel)]
runTweakInChain' :: forall (m :: * -> *) a.
MonadPlus m =>
Tweak m a -> TxSkel -> m [(a, TxSkel)]
runTweakInChain' Tweak m a
tweak = ListT m (a, TxSkel) -> m [(a, TxSkel)]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
ListT.toList (ListT m (a, TxSkel) -> m [(a, TxSkel)])
-> (TxSkel -> ListT m (a, TxSkel)) -> TxSkel -> m [(a, TxSkel)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tweak m a -> TxSkel -> ListT m (a, TxSkel)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT Tweak m a
tweak
runTweak :: (MonadPlus m) => Tweak (MockChainT m) a -> TxSkel -> m (MockChainReturn (a, TxSkel))
runTweak :: forall (m :: * -> *) a.
MonadPlus m =>
Tweak (MockChainT m) a -> TxSkel -> m (MockChainReturn (a, TxSkel))
runTweak = InitialDistribution
-> Tweak (MockChainT m) a
-> TxSkel
-> m (MockChainReturn (a, TxSkel))
forall (m :: * -> *) a.
MonadPlus m =>
InitialDistribution
-> Tweak (MockChainT m) a
-> TxSkel
-> m (MockChainReturn (a, TxSkel))
runTweakFrom InitialDistribution
forall a. Default a => a
def
runTweakFrom :: (MonadPlus m) => InitialDistribution -> Tweak (MockChainT m) a -> TxSkel -> m (MockChainReturn (a, TxSkel))
runTweakFrom :: forall (m :: * -> *) a.
MonadPlus m =>
InitialDistribution
-> Tweak (MockChainT m) a
-> TxSkel
-> m (MockChainReturn (a, TxSkel))
runTweakFrom InitialDistribution
initDist Tweak (MockChainT m) a
tweak = InitialDistribution
-> MockChainT m (a, TxSkel) -> m (MockChainReturn (a, TxSkel))
forall (m :: * -> *) a.
Monad m =>
InitialDistribution -> MockChainT m a -> m (MockChainReturn a)
runMockChainTFromInitDist InitialDistribution
initDist (MockChainT m (a, TxSkel) -> m (MockChainReturn (a, TxSkel)))
-> (TxSkel -> MockChainT m (a, TxSkel))
-> TxSkel
-> m (MockChainReturn (a, TxSkel))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tweak (MockChainT m) a -> TxSkel -> MockChainT m (a, TxSkel)
forall (m :: * -> *) a.
MonadPlus m =>
Tweak m a -> TxSkel -> m (a, TxSkel)
runTweakInChain Tweak (MockChainT m) a
tweak
data UntypedTweak m where
UntypedTweak :: Tweak m a -> UntypedTweak m
failingTweak :: (MonadTweak m) => m a
failingTweak :: forall (m :: * -> *) a. MonadTweak m => m a
failingTweak = m a
forall a. m a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
doNothingTweak :: (MonadTweak m) => m ()
doNothingTweak :: forall (m :: * -> *). MonadTweak m => m ()
doNothingTweak = () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ensureFailingTweak :: (MonadPlus m) => Tweak m a -> Tweak m ()
ensureFailingTweak :: forall (m :: * -> *) a. MonadPlus m => Tweak m a -> Tweak m ()
ensureFailingTweak Tweak m a
comp = do
TxSkel
skel <- StateT TxSkel (ListT m) TxSkel
forall s (m :: * -> *). MonadState s m => m s
get
[(a, TxSkel)]
res <- ListT m [(a, TxSkel)] -> StateT TxSkel (ListT m) [(a, TxSkel)]
forall (m :: * -> *) a. Monad m => m a -> StateT TxSkel m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ListT m [(a, TxSkel)] -> StateT TxSkel (ListT m) [(a, TxSkel)])
-> ListT m [(a, TxSkel)] -> StateT TxSkel (ListT m) [(a, TxSkel)]
forall a b. (a -> b) -> a -> b
$ m [(a, TxSkel)] -> ListT m [(a, TxSkel)]
forall (m :: * -> *) a. Monad m => m a -> ListT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m [(a, TxSkel)] -> ListT m [(a, TxSkel)])
-> m [(a, TxSkel)] -> ListT m [(a, TxSkel)]
forall a b. (a -> b) -> a -> b
$ Tweak m a -> TxSkel -> m [(a, TxSkel)]
forall (m :: * -> *) a.
MonadPlus m =>
Tweak m a -> TxSkel -> m [(a, TxSkel)]
runTweakInChain' Tweak m a
comp TxSkel
skel
Bool -> Tweak m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Tweak m ()) -> Bool -> Tweak m ()
forall a b. (a -> b) -> a -> b
$ [(a, TxSkel)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(a, TxSkel)]
res
viewTweak :: (MonadTweak m, Is k A_Getter) => Optic' k is TxSkel a -> m a
viewTweak :: forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Getter) =>
Optic' k is TxSkel a -> m a
viewTweak Optic' k is TxSkel a
optic = m TxSkel
forall (m :: * -> *). MonadTweak m => m TxSkel
getTxSkel m TxSkel -> (TxSkel -> a) -> m a
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Optic' k is TxSkel a -> TxSkel -> a
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' k is TxSkel a
optic
iviewTweak :: (MonadTweak m, Is k A_Getter) => Optic' k (WithIx is) TxSkel a -> m (is, a)
iviewTweak :: forall (m :: * -> *) k is a.
(MonadTweak m, Is k A_Getter) =>
Optic' k (WithIx is) TxSkel a -> m (is, a)
iviewTweak Optic' k (WithIx is) TxSkel a
optic = m TxSkel
forall (m :: * -> *). MonadTweak m => m TxSkel
getTxSkel m TxSkel -> (TxSkel -> (is, a)) -> m (is, a)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Optic' k (WithIx is) TxSkel a -> TxSkel -> (is, a)
forall k (is :: IxList) i s a.
(Is k A_Getter, HasSingleIndex is i) =>
Optic' k is s a -> s -> (i, a)
iview Optic' k (WithIx is) TxSkel a
optic
viewAllTweak :: (MonadTweak m, Is k A_Fold) => Optic' k is TxSkel a -> m [a]
viewAllTweak :: forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Fold) =>
Optic' k is TxSkel a -> m [a]
viewAllTweak Optic' k is TxSkel a
optic = m TxSkel
forall (m :: * -> *). MonadTweak m => m TxSkel
getTxSkel m TxSkel -> (TxSkel -> [a]) -> m [a]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Optic' k is TxSkel a -> TxSkel -> [a]
forall k (is :: IxList) s a.
Is k A_Fold =>
Optic' k is s a -> s -> [a]
toListOf Optic' k is TxSkel a
optic
setTweak :: (MonadTweak m, Is k A_Setter) => Optic' k is TxSkel a -> a -> m ()
setTweak :: forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> m ()
setTweak Optic' k is TxSkel a
optic = Optic' k is TxSkel a -> (a -> a) -> m ()
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> (a -> a) -> m ()
overTweak Optic' k is TxSkel a
optic ((a -> a) -> m ()) -> (a -> a -> a) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a -> a
forall a b. a -> b -> a
const
overTweak :: (MonadTweak m, Is k A_Setter) => Optic' k is TxSkel a -> (a -> a) -> m ()
overTweak :: forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> (a -> a) -> m ()
overTweak Optic' k is TxSkel a
optic a -> a
change = m TxSkel
forall (m :: * -> *). MonadTweak m => m TxSkel
getTxSkel m TxSkel -> (TxSkel -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= TxSkel -> m ()
forall (m :: * -> *). MonadTweak m => TxSkel -> m ()
putTxSkel (TxSkel -> m ()) -> (TxSkel -> TxSkel) -> TxSkel -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is TxSkel a -> (a -> a) -> TxSkel -> TxSkel
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over Optic' k is TxSkel a
optic a -> a
change
overMaybeTweak :: (MonadTweak m, Is k A_Traversal) => Optic' k is TxSkel a -> (a -> Maybe a) -> m [a]
overMaybeTweak :: forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Traversal) =>
Optic' k is TxSkel a -> (a -> Maybe a) -> m [a]
overMaybeTweak Optic' k is TxSkel a
optic a -> Maybe a
mChange = Optic' k is TxSkel a
-> (a -> Maybe a) -> (Integer -> Bool) -> m [a]
forall a (m :: * -> *) k (is :: IxList).
(MonadTweak m, Is k A_Traversal) =>
Optic' k is TxSkel a
-> (a -> Maybe a) -> (Integer -> Bool) -> m [a]
overMaybeSelectingTweak Optic' k is TxSkel a
optic a -> Maybe a
mChange (Bool -> Integer -> Bool
forall a b. a -> b -> a
const Bool
True)
overMaybeSelectingTweak ::
forall a m k is.
(MonadTweak m, Is k A_Traversal) =>
Optic' k is TxSkel a ->
(a -> Maybe a) ->
(Integer -> Bool) ->
m [a]
overMaybeSelectingTweak :: forall a (m :: * -> *) k (is :: IxList).
(MonadTweak m, Is k A_Traversal) =>
Optic' k is TxSkel a
-> (a -> Maybe a) -> (Integer -> Bool) -> m [a]
overMaybeSelectingTweak Optic' k is TxSkel a
optic a -> Maybe a
mChange Integer -> Bool
select = do
[a]
allFoci <- Optic' A_Lens '[] TxSkel [a] -> m [a]
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Getter) =>
Optic' k is TxSkel a -> m a
viewTweak (Optic' A_Lens '[] TxSkel [a] -> m [a])
-> Optic' A_Lens '[] TxSkel [a] -> m [a]
forall a b. (a -> b) -> a -> b
$ Optic' k is TxSkel a -> Optic' A_Lens '[] TxSkel [a]
forall k (is :: IxList) s t a.
Is k A_Traversal =>
Optic k is s t a a -> Lens s t [a] [a]
partsOf Optic' k is TxSkel a
optic
let evaluatedFoci :: [(a, Maybe a)]
evaluatedFoci :: [(a, Maybe a)]
evaluatedFoci =
(Integer, [(a, Maybe a)]) -> [(a, Maybe a)]
forall a b. (a, b) -> b
snd ((Integer, [(a, Maybe a)]) -> [(a, Maybe a)])
-> (Integer, [(a, Maybe a)]) -> [(a, Maybe a)]
forall a b. (a -> b) -> a -> b
$
(Integer -> a -> (Integer, (a, Maybe a)))
-> Integer -> [a] -> (Integer, [(a, Maybe a)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL
( \Integer
i a
unmodifiedFocus ->
case a -> Maybe a
mChange a
unmodifiedFocus of
Just a
modifiedFocus ->
if Integer -> Bool
select Integer
i
then (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1, (a
unmodifiedFocus, a -> Maybe a
forall a. a -> Maybe a
Just a
modifiedFocus))
else (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1, (a
unmodifiedFocus, Maybe a
forall a. Maybe a
Nothing))
Maybe a
Nothing -> (Integer
i, (a
unmodifiedFocus, Maybe a
forall a. Maybe a
Nothing))
)
Integer
0
[a]
allFoci
Optic' A_Lens '[] TxSkel [a] -> [a] -> m ()
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> m ()
setTweak (Optic' k is TxSkel a -> Optic' A_Lens '[] TxSkel [a]
forall k (is :: IxList) s t a.
Is k A_Traversal =>
Optic k is s t a a -> Lens s t [a] [a]
partsOf Optic' k is TxSkel a
optic) ([a] -> m ()) -> [a] -> m ()
forall a b. (a -> b) -> a -> b
$ ((a, Maybe a) -> a) -> [(a, Maybe a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> Maybe a -> a) -> (a, Maybe a) -> a
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe) [(a, Maybe a)]
evaluatedFoci
[a] -> m [a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> m [a]) -> [a] -> m [a]
forall a b. (a -> b) -> a -> b
$
((a, Maybe a) -> Maybe a) -> [(a, Maybe a)] -> [a]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe
(\(a
original, Maybe a
mNew) -> if Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
mNew then a -> Maybe a
forall a. a -> Maybe a
Just a
original else Maybe a
forall a. Maybe a
Nothing)
[(a, Maybe a)]
evaluatedFoci
combineModsTweak ::
(Eq is, Is k A_Traversal, MonadTweak m) =>
([is] -> [[is]]) ->
Optic' k (WithIx is) TxSkel x ->
(is -> x -> m [(x, l)]) ->
m [l]
combineModsTweak :: forall is k (m :: * -> *) x l.
(Eq is, Is k A_Traversal, MonadTweak m) =>
([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel x
-> (is -> x -> m [(x, l)])
-> m [l]
combineModsTweak [is] -> [[is]]
groupings Optic' k (WithIx is) TxSkel x
optic is -> x -> m [(x, l)]
changes = do
([is]
indexes, [x]
foci) <- Optic' A_Lens (WithIx [is]) TxSkel [x] -> m ([is], [x])
forall (m :: * -> *) k is a.
(MonadTweak m, Is k A_Getter) =>
Optic' k (WithIx is) TxSkel a -> m (is, a)
iviewTweak (Optic' k (WithIx is) TxSkel x
-> Optic' A_Lens (WithIx [is]) TxSkel [x]
forall k (is :: IxList) i s t a.
(Is k A_Traversal, HasSingleIndex is i) =>
Optic k is s t a a -> IxLens [i] s t [a] [a]
ipartsOf Optic' k (WithIx is) TxSkel x
optic)
[m [l]] -> m [l]
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum ([m [l]] -> m [l]) -> [m [l]] -> m [l]
forall a b. (a -> b) -> a -> b
$
([is] -> m [l]) -> [[is]] -> [m [l]]
forall a b. (a -> b) -> [a] -> [b]
map
( \[is]
grouping -> do
let mChangedFoci :: [m [(x, Either () l)]]
mChangedFoci =
(is -> x -> m [(x, Either () l)])
-> [is] -> [x] -> [m [(x, Either () l)]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
( \is
i x
a ->
if is
i is -> [is] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [is]
grouping
then ((x, l) -> (x, Either () l)) -> [(x, l)] -> [(x, Either () l)]
forall a b. (a -> b) -> [a] -> [b]
map ((l -> Either () l) -> (x, l) -> (x, Either () l)
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second l -> Either () l
forall a b. b -> Either a b
Right) ([(x, l)] -> [(x, Either () l)])
-> m [(x, l)] -> m [(x, Either () l)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> is -> x -> m [(x, l)]
changes is
i x
a
else [(x, Either () l)] -> m [(x, Either () l)]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [(x
a, () -> Either () l
forall a b. a -> Either a b
Left ())]
)
[is]
indexes
[x]
foci
[[(x, Either () l)]]
changedFoci <- [m [(x, Either () l)]] -> m [[(x, Either () l)]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence [m [(x, Either () l)]]
mChangedFoci
[m [l]] -> m [l]
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, MonadPlus m) =>
t (m a) -> m a
msum ([m [l]] -> m [l]) -> [m [l]] -> m [l]
forall a b. (a -> b) -> a -> b
$
([(x, Either () l)] -> m [l]) -> [[(x, Either () l)]] -> [m [l]]
forall a b. (a -> b) -> [a] -> [b]
map
( \[(x, Either () l)]
combination -> do
Optic' A_Lens '[] TxSkel [x] -> [x] -> m ()
forall (m :: * -> *) k (is :: IxList) a.
(MonadTweak m, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> m ()
setTweak (Optic' k (WithIx is) TxSkel x -> Optic' A_Lens '[] TxSkel [x]
forall k (is :: IxList) s t a.
Is k A_Traversal =>
Optic k is s t a a -> Lens s t [a] [a]
partsOf Optic' k (WithIx is) TxSkel x
optic) ([x] -> m ()) -> [x] -> m ()
forall a b. (a -> b) -> a -> b
$ ((x, Either () l) -> x) -> [(x, Either () l)] -> [x]
forall a b. (a -> b) -> [a] -> [b]
map (x, Either () l) -> x
forall a b. (a, b) -> a
fst [(x, Either () l)]
combination
[l] -> m [l]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([l] -> m [l]) -> [l] -> m [l]
forall a b. (a -> b) -> a -> b
$ ((x, Either () l) -> Maybe l) -> [(x, Either () l)] -> [l]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Either () l -> Maybe l
forall a b. Either a b -> Maybe b
rightToMaybe (Either () l -> Maybe l)
-> ((x, Either () l) -> Either () l) -> (x, Either () l) -> Maybe l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (x, Either () l) -> Either () l
forall a b. (a, b) -> b
snd) [(x, Either () l)]
combination
)
([[(x, Either () l)]] -> [[(x, Either () l)]]
forall a. [[a]] -> [[a]]
allCombinations [[(x, Either () l)]]
changedFoci)
)
([is] -> [[is]]
groupings [is]
indexes)
where
allCombinations :: [[a]] -> [[a]]
allCombinations :: forall a. [[a]] -> [[a]]
allCombinations [] = [[]]
allCombinations ([a]
first : [[a]]
rest) = [a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
xs | a
x <- [a]
first, [a]
xs <- [[a]] -> [[a]]
forall a. [[a]] -> [[a]]
allCombinations [[a]]
rest]
selectP :: (a -> Bool) -> Prism' a a
selectP :: forall a. (a -> Bool) -> Prism' a a
selectP a -> Bool
prop = (a -> a) -> (a -> Maybe a) -> Prism a a a a
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism' a -> a
forall a. a -> a
id (\a
a -> if a -> Bool
prop a
a then a -> Maybe a
forall a. a -> Maybe a
Just a
a else Maybe a
forall a. Maybe a
Nothing)