final-0.1: utility to add extra safety to monadic returns

Safe HaskellSafe-Inferred

Control.Final

Contents

Description

The Final library makes it possible to point out return values in (monadic) functions. This adds extra compile-time safety to your code, because the compiler will warn you if marked return values accidentally became middle parts of a big function written with do notation.

A worked out example can be found in Control.Final.Example, and an alternative approach is considered in Control.Final.Alternatives.

Synopsis

Most common, monadic usage

final :: (Monad m, FinalClass f) => x -> m (f x)Source

Use this instead of return when you want to mark this point as a final return for the corresponding runFinal.

runFinal :: Monad m => m (Final a) -> m aSource

Most commonly used at the beginning of functions to mark the point in the code where final calls "return to".

This compiles:

 simple = runFinal $ do
   print "line1"
   do return False
      return True
   final True

This fails at the first "final True":

 simple = runFinal $ do
   print "line1"
   do return False
      final True
   final True

joinFinal :: Monad m => m (Final (m a)) -> m aSource

Useful when the final return value is a monadic computation itself that after returned has to be joined into the current computation.

atomicJoinFinal :: (Functor m, MonadIO m) => STM (Final (m a)) -> m aSource

A version of atomically, that joins and runFinals. This is the most common usage for the author. Details and example can be found in Control.Final.Example.

Related functions

atomic :: MonadIO m => STM a -> m aSource

MonadIO version of atomically. Not really related to Final, but if we already have atomicJoinFinal in this module, it makes sense to provide this too.

Usage in pure code

class FinalClass f whereSource

This class is the main idea behind Final. finalV is in a type class, so we we can have to instances, therefore if used incorrectly the compiler sees an ambiguity.

Methods

finalV :: a -> f aSource

runFinalV :: Final a -> aSource

Usage example:

 pureExample p =
   runFinalV $ case p of
     True -> finalV "quux"
     False -> finalV "foobar"