Controller is now also MonadState.

portnov [2009-07-14 04:17:54]
Controller is now also MonadState.
Filename
Framework/Controller.hs
diff --git a/Framework/Controller.hs b/Framework/Controller.hs
index f313cbe..b8347c2 100644
--- a/Framework/Controller.hs
+++ b/Framework/Controller.hs
@@ -22,11 +22,12 @@ module Framework.Controller
      returnNow, reject,
      concatC, changeR,
      assertC,
-     evalController,
-     evalRightNow
+     evalController
+--      evalRightNow
     ) where

 import Control.Monad.Reader.Class
+import Control.Monad.State.Class
 import Control.Monad.Trans

 import Framework.Types
@@ -42,7 +43,7 @@ data ControllerResult r a = Reject                 -- ^ `No, I wann't process th

 -- | Controller itself
 newtype Controller s r a = Controller {
-    runController :: s -> IO (ControllerResult r a)
+    runController :: s -> IO (ControllerResult r a, s)
     }

 -- | Type of application-level controllers
@@ -63,25 +64,31 @@ type ControllerExcHandler = HttpRequest -> Int -> String -> AController ()

 instance Monad (Controller s r) where
 --     return :: a -> Controller s a
-    return v = Controller $ \_ -> return (Result v)
+    return v = Controller $ \s -> return (Result v, s)

 --     (>>=) :: Controller s a -> (a -> Controller s b) -> Controller s b
     Controller cmd >>= f =
         Controller $ \s -> do       -- `do` in IO
-            res <- cmd s
+            (res, s') <- cmd s
             case res of
-                Reject     -> return Reject
-                RightNow resp -> return $ RightNow resp
-                Result res'   -> (runController . f) res' s
+                Reject     -> return (Reject, s)
+                RightNow resp -> return (RightNow resp, s)
+                Result res'   -> (runController . f) res' s'
+
+instance MonadState s (Controller s r) where
+    get = Controller $ \s -> return (Result s, s)
+    put s = Controller $ \_ -> return (Result (), s)

 instance MonadReader s (Controller s r) where
-    ask = Controller $ \s -> return (Result s)
+    ask = Controller $ \s -> return (Result s, s)
     local f m = Controller $ runController m . f

 instance MonadIO (Controller s r) where
     -- liftIO :: IO a -> Controller s r a
     -- | `Lift' an IO action into Controller
-    liftIO act = Controller $ \_ -> Result `fmap` act
+    liftIO act = Controller $ \s -> do
+        res <- act
+        return (Result res, s)

 ---------------------------------------------------------------------------------------------
 -- * Controller-monad specific functions
@@ -92,7 +99,7 @@ concatC :: [Controller b [a] [a]]  -- ^ List of controllers
 concatC cs = do
     s <- ask
     rs <- liftIO $ mapM (flip runController s) cs
-    return $ process rs
+    return $ process $ map fst rs
   where
     process []                = []
     process (Reject:_)        = []
@@ -104,7 +111,7 @@ changeR :: Controller s r a -> Controller s q a
 changeR m = do
     s <- ask
     r <- liftIO $ runController m s
-    case r of
+    case fst r of
       Reject -> reject
       RightNow t -> reject
       Result x -> return x
@@ -118,17 +125,19 @@ assertC b =

 -- | Return given value and do not evaluate following computations
 returnNow ::  r -> Controller s r a
-returnNow v = Controller $ \_ -> return (RightNow v)
+returnNow v = Controller $ \s -> return (RightNow v, s)

 -- | Reject this computation
 reject :: Controller s r a
-reject = Controller $ \_ -> return Reject
+reject = Controller $ \s -> return (Reject, s)

 -- | Evaluate controller with given configuration
 evalController :: Controller s a a              -- ^ Controller
                -> s                             -- ^ Configuration for controller
                -> IO (Maybe a)
-evalController m s = anyResult `fmap` (runController m s)
+evalController m s = do
+    (res, s') <- (runController m s)
+    return $ anyResult res
     where
         -- | Convert any result to Maybe HttpResponse
         anyResult ::  ControllerResult a a -> Maybe a
@@ -138,13 +147,13 @@ evalController m s = anyResult `fmap` (runController m s)


 -- | Same as @evalController@, but return a value only if controller returns RightNow v.
-evalRightNow :: Controller s r a                 -- ^ Controller
-             -> s                                -- ^ Configuration for controller
-             -> IO (Maybe r)
-evalRightNow m s = anyResult `fmap` (runController m s)
-    where
-       anyResult :: ControllerResult r a -> Maybe r
-       anyResult Reject = Nothing
-       anyResult (RightNow r) = Just r
-       anyResult (Result _) = Nothing
+-- evalRightNow :: Controller s r a                 -- ^ Controller
+--              -> s                                -- ^ Configuration for controller
+--              -> IO (Maybe r)
+-- evalRightNow m s = anyResult `fmap` (runController m s)
+--     where
+--        anyResult :: ControllerResult r a -> Maybe r
+--        anyResult Reject = Nothing
+--        anyResult (RightNow r) = Just r
+--        anyResult (Result _) = Nothing
ViewGit