Skip to content

Commit

Permalink
Merge pull request #684 from IntersectMBO/fix-monadwarning-haddock
Browse files Browse the repository at this point in the history
Fix issues in `MonadWarning` Haddock
  • Loading branch information
palas authored Mar 29, 2024
2 parents f94b0ac + 0212c80 commit ee1ce1f
Showing 1 changed file with 30 additions and 16 deletions.
46 changes: 30 additions & 16 deletions cardano-cli/src/Cardano/CLI/Types/MonadWarning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
--
-- This module defines the 'MonadWarning' type class, which provides a common
-- interface for monads that support reporting warning messages without
-- aborting the computation (unlike with exceptions, Either, or MonadFail,
-- which either fail or return a value).
-- aborting the computation (unlike with exceptions, 'Either', or
-- 'MonadFail', which either fail or return a value).
--
-- It also includes two functions that instantiate it into either a 'MonadIO'
-- ('runWarningIO') or a 'StateT' monad with a '[String]' as state
-- ('runWarningIO') or a 'StateT' monad with a @[String]@ as state
-- ('runWarningStateT') respectively.
--
-- In the case of 'MonadIO', warnings are printed to 'stderr'.
-- In the case of 'StateT', with a '[String]' state, warnings are added to the
-- In the case of 'StateT', with a @[String]@ state, warnings are added to the
-- list in the state.
--
-- By using the 'MonadWarning' type class, users can write code that remains
Expand Down Expand Up @@ -40,6 +40,8 @@

module Cardano.CLI.Types.MonadWarning
( MonadWarning(..)
, WarningIO
, WarningStateT
, eitherToWarning
, runWarningIO
, runWarningStateT
Expand All @@ -50,33 +52,45 @@ import Control.Monad.State (MonadState (..))
import Control.Monad.Trans.State (StateT)
import System.IO (hPutStrLn, stderr)

-- | Type class for monads that support reporting warnings.
-- | Type class for monads that support reporting warnings without aborting
-- their execution in the process.
class Monad m => MonadWarning m where
-- | Report a warning issue.
-- | Report a non-fatal issue.
reportIssue :: String -- ^ The warning message to report.
-> m () -- ^ The action that reports the warning.

-- | Wrapper newtype for 'MonadIO' with 'MonadWarning' instance.
-- We need to have wrapper to avoid overlapping instances.
newtype WarningIO m a = WarningIO { runWarningIO :: m a }
deriving (Functor, Applicative, Monad, MonadIO)
-- This type is not meant to be constructed directly but just to serve
-- as an instance of 'MonadWarning' that can be converted to 'MonadIO'.
-- It is only necessary in order to avoid overlapping instances.
newtype WarningIO m a = WarningIO {
runWarningIO :: m a
-- ^ Interpret a 'MonadWarning' as a 'MonadIO' by reporting
-- warnings to 'stderr'.
} deriving (Functor, Applicative, Monad, MonadIO)

-- | This instance prints the issue to the 'stderr'.
-- | This instance prints the issue to 'stderr'.
instance MonadIO m => MonadWarning (WarningIO m) where
reportIssue :: String -> WarningIO m ()
reportIssue issue = liftIO (hPutStrLn stderr issue)

-- | Wrapper newtype for 'StateT [String]' with 'MonadWarning' instance.
newtype WarningStateT m a = WarningStateT { runWarningStateT :: StateT [String] m a }
deriving (Functor, Applicative, Monad, MonadState [String])
-- | Wrapper newtype for @StateT [String]@ with 'MonadWarning' instance.
-- This type is not meant to be constructed directly but just to serve
-- as an instance of 'MonadWarning' that can be converted to 'StateT'.
-- It is only necessary in order to avoid overlapping instances.
newtype WarningStateT m a = WarningStateT {
runWarningStateT :: StateT [String] m a
-- ^ Interpret a 'MonadWarning' as a @StateT [String]@ monad,
-- by accumulating warnings into the state.
} deriving (Functor, Applicative, Monad, MonadState [String])

-- | This instance adds the issue to the '[String]' in the state.
-- | This instance adds the issue to the @[String]@ in the state.
instance Monad m => MonadWarning (WarningStateT m) where
reportIssue :: String -> WarningStateT m ()
reportIssue issue = state (\ x -> ((), issue : x))

-- | Convert an 'Either' into a 'MonadWarning'. If 'Either' is 'Left'
-- it returns the default value (first parameter) and reports the value
-- as an error. -- If 'Either' is 'Right' it just returns the value.
-- it returns the default value (first parameter) and reports the 'String'
-- as an error. If 'Either' is 'Right' it just returns that value.
eitherToWarning :: MonadWarning m => a -> Either String a -> m a
eitherToWarning def = either (\issue -> do {reportIssue issue; return def}) return

0 comments on commit ee1ce1f

Please sign in to comment.