commander-cli 0.8.0.0 → 0.9.0.0
raw patch · 2 files changed
+2/−142 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Monad.Commander: Action :: (state -> m (CommanderT state m a, state)) -> CommanderT state m a
- Control.Monad.Commander: Defeat :: CommanderT state m a
- Control.Monad.Commander: Victory :: a -> CommanderT state m a
- Control.Monad.Commander: data CommanderT state m a
- Control.Monad.Commander: instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Monad.Commander.CommanderT state m)
- Control.Monad.Commander: instance Control.Monad.Trans.Class.MonadTrans (Control.Monad.Commander.CommanderT state)
- Control.Monad.Commander: instance GHC.Base.Functor m => GHC.Base.Functor (Control.Monad.Commander.CommanderT state m)
- Control.Monad.Commander: instance GHC.Base.Monad m => GHC.Base.Alternative (Control.Monad.Commander.CommanderT state m)
- Control.Monad.Commander: instance GHC.Base.Monad m => GHC.Base.Applicative (Control.Monad.Commander.CommanderT state m)
- Control.Monad.Commander: instance GHC.Base.Monad m => GHC.Base.Monad (Control.Monad.Commander.CommanderT state m)
- Control.Monad.Commander: runCommanderT :: Monad m => CommanderT state m a -> state -> m (Maybe a)
- Options.Commander: Action :: (state -> m (CommanderT state m a, state)) -> CommanderT state m a
+ Options.Commander: Action :: (state -> f (CommanderT state f a, state)) -> CommanderT state a
- Options.Commander: Defeat :: CommanderT state m a
+ Options.Commander: Defeat :: CommanderT state a
- Options.Commander: Victory :: a -> CommanderT state m a
+ Options.Commander: Victory :: a -> CommanderT state a
- Options.Commander: data CommanderT state m a
+ Options.Commander: data CommanderT state (f :: Type -> Type) a
Files
- commander-cli.cabal +2/−2
- src/Control/Monad/Commander.hs +0/−140
commander-cli.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name: commander-cli-version: 0.8.0.0+version: 0.9.0.0 synopsis: A command line argument/option parser library description: A command line argument/option parser library. homepage: https://github.com/SamuelSchlesinger/commander-cli@@ -20,7 +20,7 @@ location: https://github.com/samuelschlesinger/commander-cli library- exposed-modules: Options.Commander, Control.Monad.Commander+ exposed-modules: Options.Commander other-extensions: ViewPatterns, DerivingVia, StandaloneDeriving,
− src/Control/Monad/Commander.hs
@@ -1,140 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{- |-Module: Control.Monad.Commander-Description: A monad for stateful, backtracking computations-Copyright: (c) Samuel Schlesinger 2020-License: MIT-Maintainer: sgschlesinger@gmail.com-Stability: experimental-Portability: POSIX, Windows--}-module Control.Monad.Commander (- -- ** The CommanderT Monad- {- |- The 'CommanderT' monad is how your CLI programs are interpreted by 'run'.- It has the ability to backtrack and it maintains some state.- -}- CommanderT(Action, Defeat, Victory), runCommanderT,-) where--import Control.Monad (ap)-import Control.Monad.Trans (MonadTrans, lift, liftIO, MonadIO)-import Control.Applicative (Alternative(empty, (<|>)))---- | A 'CommanderT' action is a metaphor for a military commander. At each--- step, we have a new 'Action' to take, or we could have experienced--- 'Defeat', or we can see 'Victory'. While a real life commander--- worries about moving his troops around in order to achieve a victory in--- battle, a 'CommanderT' worries about iteratively transforming a state --- to find some value. We will deal with the subset of these actions where--- every function must decrease the size of the state, as those are the--- actions for which this is a monad.-data CommanderT state m a- = Action (state -> m (CommanderT state m a, state))- | Defeat- | Victory a- deriving Functor---- | We can run a 'CommanderT' action on a state and see if it has--- a successful campaign.-runCommanderT :: Monad m - => CommanderT state m a - -> state - -> m (Maybe a)-runCommanderT (Action action) state = do- (action', state') <- action state- runCommanderT action' state'-runCommanderT Defeat _ = return Nothing-runCommanderT (Victory a) _ = return (Just a)--instance (Monad m) => Applicative (CommanderT state m) where- (<*>) = ap- pure = Victory--instance MonadTrans (CommanderT state) where- lift ma = Action $ \state -> do- a <- ma- return (pure a, state)--instance MonadIO m => MonadIO (CommanderT state m) where- liftIO ma = Action $ \state -> do- a <- liftIO ma- return (pure a, state)---- Return laws:--- Goal: return a >>= k = k a--- Proof: return a >>= k --- = Victory a >>= k --- = k a --- = k a--- Goal: m >>= return = m--- Proof:--- Case 1: Defeat >>= return = Defeat--- Case 2: Victory a >>= return --- = Victory a--- Case 3: Action action >>= return--- = Action $ \state -> do--- (action', state') <- action state--- return (action' >>= return, state')------ Case 3 serves as an inductive proof only if action' is a strictly smaller action--- than action!------ Bind laws:--- Goal: m >>= (\x -> k x >>= h) = (m >>= k) >>= h--- Proof: --- Case 1: Defeat >>= _ = Defeat--- Case 2: Victory a >>= (\x -> k x >>= f)--- = k a >>= f--- = (Victory a >>= k) >>= f--- Case 3: Action action >>= (\x -> k x >>= h)--- = Action $ \state -> do--- (action', state') <- action state--- return (action' >>= (\x -> k x >>= h), state')--- = Action $ \state -> do--- (action', state') <- action state--- return ((action' >>= k) >>= h, state') -- by IH--- On the other hand,--- (Action action >>= k) >>= h--- = Action (\state -> do--- (action', state') <- action state--- return (action' >>= k, state') >>= h--- = Action $ \state -> do--- (action', state') <- action state--- return ((action' >>= k) >>= h, state')--- --- This completes our proof for the case when these are finite.--- Basically, we require that the stream an action produces is strictly--- smaller than any other streams, for all state inputs. The ways that we--- use this monad transformer satisify this constraint. If this--- constraint is not met, many of our functions will return bottom.------ We can certainly have functions that operate on these things and--- change them safely, without violating this constraint. All of the--- functions that we define on CommanderT programs preserve this--- property.------ An example of a violating term might be:------ violator :: CommanderT state m--- violator = Action (\state -> return (violator, state))------ The principled way to include this type would be to parameterize it by--- a natural number and have that natural number decrease over time, but--- to enforce that in Haskell we couldn't have the monad instance--- anyways. This is the way to go for now, despite the type violating the--- monad laws potentially for infinite inputs. -instance Monad m => Monad (CommanderT state m) where- Defeat >>= _ = Defeat- Victory a >>= f = f a- Action action >>= f = Action $ \state -> do- (action', state') <- action state- return (action' >>= f, state')--instance Monad m => Alternative (CommanderT state m) where- empty = Defeat - Defeat <|> a = a - v@(Victory _) <|> _ = v- Action action <|> p = Action $ \state -> do- (action', state') <- action state - return (action' <|> p, state')