packages feed

early-0.0.0: src/Control/Early.hs

-- | Early return in monads.

module Control.Early
  ( Early(..)
  , early
  , earlyThen
  ) where

--------------------------------------------------------------------------------
-- Class providing different early return types

-- | A class for things which can offer branching for early return.
--
-- The most obvious two types are 'Either' and 'Maybe'.
class Functor f => Early f where
  dispatch :: Applicative m => f a -> (a -> m (f b)) -> m (f b)

--------------------------------------------------------------------------------
-- Top-level API

-- | Early return specialized on f (for now).
early :: (Monad m, Early f) => m (f a) -> (a -> m (f b)) -> m (f b)
early m f = do
  r <- m
  dispatch r f
{-# INLINE early #-}

-- | Early return specialized on f (for now).
earlyThen :: (Monad m, Early f) => m (f a) -> m (f b) -> m (f b)
earlyThen m f = early m (const f)
{-# INLINE earlyThen #-}

--------------------------------------------------------------------------------
-- Instances

instance Early (Either e) where
  dispatch r f =
    case r of
      Left e -> pure (Left e)
      Right x -> f x
  {-# INLINE dispatch #-}

instance Early Maybe where
  dispatch r f =
    case r of
      Nothing -> pure Nothing
      Just x -> f x
  {-# INLINE dispatch #-}