explicit-sharing-0.4.0.1: Control/Monad/Sharing/Classes.hs
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, Rank2Types #-}
-- |
-- Module : Control.Monad.Sharing.Classes
-- Copyright : Chung-chieh Shan, Oleg Kiselyov, and Sebastian Fischer
-- License : PublicDomain
-- Maintainer : Sebastian Fischer <mailto:sebf@informatik.uni-kiel.de>
-- Stability : experimental
--
-- This library provides type classes for explicit sharing of monadic
-- effects. Usually you don't need to import this library as it is
-- reexported by the module 'Control.Monad.Sharing'. You may want to
-- do so, however, when writing your own implementation of explicit
-- sharing.
module Control.Monad.Sharing.Classes (
Sharing(..), Trans(..), eval
) where
import Control.Monad ( liftM, join )
-- | Interface of monads that support explicit sharing.
class Sharing m
where
-- |
-- Yields an action that returns the same results as the given
-- action but whose effects are only executed once. Especially, when
-- the resulting action is duplicated it returns the same result at
-- every occurrence.
share :: Trans m a a => m a -> m (m a)
-- |
-- Interface to transform nested monadic data types. The provided
-- function 'trans' is supposed to map the given function on every
-- monadic argument. The result of 'trans' may be of the same type as
-- the argument but can also be of a different type, e.g. to convert a
-- value with nested monadic arguments to a corresponding value
-- without.
--
-- We provide instances of the 'Trans' class for some predefined
-- Haskell types. For flat types the function 'trans' just returns its
-- argument which has no arguments to which the given function could
-- be applied.
class Trans m a b
where
trans :: (forall c d . Trans m c d => m c -> m (m d)) -> a -> m b
-- |
-- Lifts all monadic effects in nested monadic values to the top
-- level. If @m@ is a monad for non-determinism and the argument a
-- data structure with nested non-determinism then the result
-- corresponds to the normal form of the argument.
eval :: (Monad m, Trans m a b) => a -> m b
eval = trans (\a -> liftM return (a >>= eval))
instance Monad m => Trans m Bool Bool
where
trans _ = return
instance Monad m => Trans m Int Int
where
trans _ = return
instance Monad m => Trans m Char Char
where
trans _ = return
instance Monad m => Trans m Float Float
where
trans _ = return
instance Monad m => Trans m Double Double
where
trans _ = return
instance Monad m => Trans m [Bool] [Bool]
where
trans _ = return
instance Monad m => Trans m [Int] [Int]
where
trans _ = return
instance Monad m => Trans m [Char] [Char]
where
trans _ = return
instance Monad m => Trans m [Float] [Float]
where
trans _ = return
instance Monad m => Trans m [Double] [Double]
where
trans _ = return
-- | An instance for lists with monadic elements.
instance (Monad m, Trans m a a) => Trans m [m a] [m a]
where
trans f = mapM f
-- |
-- An instance for lists with monadic elements that lifts all monadic
-- effects to the top level and yields a list with non-monadic
-- elements.
instance (Monad m, Trans m a a) => Trans m [m a] [a]
where
trans f = mapM (join . f)