curry-base-1.0.0: src/Curry/Base/Monad.hs
{- |
Module : $Header$
Description : Monads for message handling
Copyright : 2014 - 2016 Björn Peemöller
License : BSD-3-clause
Maintainer : bjp@informatik.uni-kiel.de
Stability : experimental
The monads defined in this module provide a common way to stop execution
when some errors occur. They are used to integrate different compiler passes
smoothly.
-}
module Curry.Base.Monad
( CYIO, CYM, CYT, failMessages, failMessageAt, warnMessages, warnMessageAt
, ok, runCYIO, runCYM, runCYIOIgnWarn, runCYMIgnWarn, liftCYM, silent
) where
import Control.Monad.Identity
import Control.Monad.Trans.Except (ExceptT, mapExceptT, runExceptT, throwE)
import Control.Monad.Writer
import Curry.Base.Message (Message, posMessage)
import Curry.Base.Position
import Curry.Base.Pretty (text)
-- |Curry compiler monad transformer
type CYT m a = WriterT [Message] (ExceptT [Message] m) a
-- |Curry compiler monad based on the `IO` monad
type CYIO a = CYT IO a
-- |Pure Curry compiler monad
type CYM a = CYT Identity a
-- |Run an `IO`-based Curry compiler action in the `IO` monad,
-- yielding either a list of errors or a result in case of success
-- consisting of the actual result and a (possibly empty) list of warnings
runCYIO :: CYIO a -> IO (Either [Message] (a, [Message]))
runCYIO = runExceptT . runWriterT
-- |Run an pure Curry compiler action,
-- yielding either a list of errors or a result in case of success
-- consisting of the actual result and a (possibly empty) list of warnings
runCYM :: CYM a -> Either [Message] (a, [Message])
runCYM = runIdentity . runExceptT . runWriterT
-- |Run an `IO`-based Curry compiler action in the `IO` monad,
-- yielding either a list of errors or a result in case of success.
runCYIOIgnWarn :: CYIO a -> IO (Either [Message] a)
runCYIOIgnWarn = runExceptT . (liftM fst) . runWriterT
-- |Run an pure Curry compiler action,
-- yielding either a list of errors or a result in case of success.
runCYMIgnWarn :: CYM a -> Either [Message] a
runCYMIgnWarn = runIdentity . runExceptT . (liftM fst) . runWriterT
-- |Failing action with a message describing the cause of failure.
failMessage :: Monad m => Message -> CYT m a
failMessage msg = failMessages [msg]
-- |Failing action with a list of messages describing the cause(s) of failure.
failMessages :: Monad m => [Message] -> CYT m a
failMessages = lift . throwE
-- |Failing action with a source code position and a `String` indicating
-- the cause of failure.
failMessageAt :: Monad m => Position -> String -> CYT m a
failMessageAt pos s = failMessage $ posMessage pos $ text s
-- |Warning with a message describing the cause of the warning.
warnMessage :: Monad m => Message -> CYT m ()
warnMessage msg = warnMessages [msg]
-- |Warning with a list of messages describing the cause(s) of the warnings.
warnMessages :: Monad m => [Message] -> CYT m ()
warnMessages msgs = tell msgs
-- |Execute a monadic action, but ignore any warnings it issues
silent :: Monad m => CYT m a -> CYT m a
silent act = censor (const []) act
-- |Warning with a source code position and a `String` indicating
-- the cause of the warning.
warnMessageAt :: Monad m => Position -> String -> CYT m ()
warnMessageAt pos s = warnMessage $ posMessage pos $ text s
-- |Lift a value into the `CYT m` monad, same as `return`.
ok :: Monad m => a -> CYT m a
ok = return
-- |Lift a pure action into an action based on another monad.
liftCYM :: Monad m => CYM a -> CYT m a
liftCYM = mapWriterT (mapExceptT (return . runIdentity))