    -- |
    -- Module      :  Cryptol.Utils.Misc
    -- Copyright   :  (c) 2014-2016 Galois, Inc.
    -- License     :  BSD3
    -- Maintainer  :  cryptol@galois.com
    -- Stability   :  provisional
    -- Portability :  portable

    {-# LANGUAGE Safe, FlexibleContexts #-}
    module Cryptol.Utils.Misc where

    import MonadLib

    import Prelude ()
    import Prelude.Compat

    -- | Apply a function to all elements of a container.
    -- Returns `Nothing` if nothing changed, and @Just container@ otherwise.
    anyJust :: Traversable t => (a -> Maybe a) -> t a -> Maybe (t a)
    anyJust :: forall (t :: * -> *) a.
    Traversable t =>
    (a -> Maybe a) -> t a -> Maybe (t a)
    anyJust a -> Maybe a
    f t a
    m = (t a, Bool) -> Maybe (t a)
    forall {a}. (a, Bool) -> Maybe a
    mk ((t a, Bool) -> Maybe (t a)) -> (t a, Bool) -> Maybe (t a)
    forall a b. (a -> b) -> a -> b
    $ Lift (t a, Bool) -> (t a, Bool)
    forall a. Lift a -> a
    runLift (Lift (t a, Bool) -> (t a, Bool))
    -> Lift (t a, Bool) -> (t a, Bool)
    forall a b. (a -> b) -> a -> b
    $ Bool -> StateT Bool Lift (t a) -> Lift (t a, Bool)
    forall i (m :: * -> *) a. i -> StateT i m a -> m (a, i)
    runStateT Bool
    False (StateT Bool Lift (t a) -> Lift (t a, Bool))
    -> StateT Bool Lift (t a) -> Lift (t a, Bool)
    forall a b. (a -> b) -> a -> b
    $ (a -> StateT Bool Lift a) -> t a -> StateT Bool Lift (t a)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> StateT Bool Lift a
    forall {m :: * -> *}. StateM m Bool => a -> m a
    upd t a
    m
      where
      mk :: (a, Bool) -> Maybe a
    mk (a
    a,Bool
    changes) = if Bool
    changes then a -> Maybe a
    forall a. a -> Maybe a
    Just a
    a else Maybe a
    forall a. Maybe a
    Nothing

      upd :: a -> m a
    upd a
    x = case a -> Maybe a
    f a
    x of
                Just a
    y  -> Bool -> m ()
    forall (m :: * -> *) i. StateM m i => i -> m ()
    set Bool
    True m () -> m a -> m a
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> a -> m a
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    y
                Maybe a
    Nothing -> a -> m a
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    x

    -- | Apply functions to both elements of a pair.
    -- Returns `Nothing` if neither changed, and @Just pair@ otherwise.
    anyJust2 :: (a -> Maybe a) -> (b -> Maybe b) -> (a,b) -> Maybe (a,b)
    anyJust2 :: forall a b.
    (a -> Maybe a) -> (b -> Maybe b) -> (a, b) -> Maybe (a, b)
    anyJust2 a -> Maybe a
    f b -> Maybe b
    g (a
    a,b
    b) =
      case (a -> Maybe a
    f a
    a, b -> Maybe b
    g b
    b) of
        (Maybe a
    Nothing, Maybe b
    Nothing) -> Maybe (a, b)
    forall a. Maybe a
    Nothing
        (Just a
    x , Maybe b
    Nothing) -> (a, b) -> Maybe (a, b)
    forall a. a -> Maybe a
    Just (a
    x, b
    b)
        (Maybe a
    Nothing, Just b
    y ) -> (a, b) -> Maybe (a, b)
    forall a. a -> Maybe a
    Just (a
    a, b
    y)
        (Just a
    x , Just b
    y ) -> (a, b) -> Maybe (a, b)
    forall a. a -> Maybe a
    Just (a
    x, b
    y)