MonadInvertIO
This commit is contained in:
parent
2f61ef6d39
commit
ab4c7e3ae2
9
Yesod.hs
9
Yesod.hs
@ -1,5 +1,4 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
{-# LANGUAGE PackageImports #-}
|
|
||||||
module Yesod
|
module Yesod
|
||||||
( module Yesod.Request
|
( module Yesod.Request
|
||||||
, module Yesod.Content
|
, module Yesod.Content
|
||||||
@ -13,7 +12,7 @@ module Yesod
|
|||||||
, Application
|
, Application
|
||||||
, lift
|
, lift
|
||||||
, liftIO
|
, liftIO
|
||||||
, MonadCatchIO
|
, MonadInvertIO
|
||||||
, mempty
|
, mempty
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ import Yesod.Form
|
|||||||
import Yesod.Widget
|
import Yesod.Widget
|
||||||
import Network.Wai (Application)
|
import Network.Wai (Application)
|
||||||
import Yesod.Hamlet
|
import Yesod.Hamlet
|
||||||
import "transformers" Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import "transformers" Control.Monad.IO.Class (liftIO)
|
import Control.Monad.IO.Class (liftIO)
|
||||||
import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO)
|
|
||||||
import Data.Monoid (mempty)
|
import Data.Monoid (mempty)
|
||||||
|
import Control.Monad.Invert (MonadInvertIO)
|
||||||
|
|||||||
@ -73,7 +73,7 @@ module Yesod.Handler
|
|||||||
, YesodApp (..)
|
, YesodApp (..)
|
||||||
, toMasterHandler
|
, toMasterHandler
|
||||||
, localNoCurrent
|
, localNoCurrent
|
||||||
, finallyHandler
|
, HandlerData
|
||||||
#if TEST
|
#if TEST
|
||||||
, testSuite
|
, testSuite
|
||||||
#endif
|
#endif
|
||||||
@ -94,17 +94,18 @@ import Control.Monad.IO.Class
|
|||||||
import Control.Monad.Trans.Class
|
import Control.Monad.Trans.Class
|
||||||
import Control.Monad.Trans.Writer
|
import Control.Monad.Trans.Writer
|
||||||
import Control.Monad.Trans.Reader
|
import Control.Monad.Trans.Reader
|
||||||
import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO)
|
|
||||||
import qualified "MonadCatchIO-transformers" Control.Monad.CatchIO as C
|
|
||||||
|
|
||||||
import System.IO
|
import System.IO
|
||||||
import qualified Network.Wai as W
|
import qualified Network.Wai as W
|
||||||
import Control.Monad.Attempt
|
import Control.Failure (Failure (failure))
|
||||||
import Data.ByteString.UTF8 (toString)
|
import Data.ByteString.UTF8 (toString)
|
||||||
import qualified Data.ByteString.Lazy.UTF8 as L
|
import qualified Data.ByteString.Lazy.UTF8 as L
|
||||||
|
|
||||||
import Text.Hamlet
|
import Text.Hamlet
|
||||||
|
|
||||||
|
import Control.Monad.Invert (MonadInvertIO (..))
|
||||||
|
import Control.Monad (liftM)
|
||||||
|
|
||||||
#if TEST
|
#if TEST
|
||||||
import Test.Framework (testGroup, Test)
|
import Test.Framework (testGroup, Test)
|
||||||
import Test.Framework.Providers.HUnit (testCase)
|
import Test.Framework.Providers.HUnit (testCase)
|
||||||
@ -153,15 +154,28 @@ toMasterHandler tm ts route (GHandler h) =
|
|||||||
-- 'WriterT' for headers and session, and an 'MEitherT' monad for handling
|
-- 'WriterT' for headers and session, and an 'MEitherT' monad for handling
|
||||||
-- special responses. It is declared as a newtype to make compiler errors more
|
-- special responses. It is declared as a newtype to make compiler errors more
|
||||||
-- readable.
|
-- readable.
|
||||||
newtype GHandler sub master a = GHandler { unGHandler ::
|
newtype GHandler sub master a =
|
||||||
ReaderT (HandlerData sub master) (
|
GHandler
|
||||||
|
{ unGHandler :: GHInner sub master a
|
||||||
|
}
|
||||||
|
deriving (Functor, Applicative, Monad, MonadIO)
|
||||||
|
|
||||||
|
type GHInner s m =
|
||||||
|
ReaderT (HandlerData s m) (
|
||||||
MEitherT HandlerContents (
|
MEitherT HandlerContents (
|
||||||
WriterT (Endo [Header]) (
|
WriterT (Endo [Header]) (
|
||||||
WriterT (Endo [(String, Maybe String)]) (
|
WriterT (Endo [(String, Maybe String)]) (
|
||||||
IO
|
IO
|
||||||
)))) a
|
))))
|
||||||
}
|
|
||||||
deriving (Functor, Applicative, Monad, MonadIO, MonadCatchIO)
|
instance MonadInvertIO (GHandler s m) where
|
||||||
|
newtype InvertedIO (GHandler s m) a =
|
||||||
|
InvGHandlerIO
|
||||||
|
{ runInvGHandlerIO :: InvertedIO (GHInner s m) a
|
||||||
|
}
|
||||||
|
type InvertedArg (GHandler s m) = (HandlerData s m, ())
|
||||||
|
invertIO = liftM (fmap InvGHandlerIO) . invertIO . unGHandler
|
||||||
|
revertIO f = GHandler $ revertIO $ liftM runInvGHandlerIO . f
|
||||||
|
|
||||||
type Endo a = a -> a
|
type Endo a = a -> a
|
||||||
|
|
||||||
@ -475,24 +489,7 @@ localNoCurrent =
|
|||||||
|
|
||||||
testSuite :: Test
|
testSuite :: Test
|
||||||
testSuite = testGroup "Yesod.Handler"
|
testSuite = testGroup "Yesod.Handler"
|
||||||
[ testCase "finally" caseFinally
|
[
|
||||||
]
|
]
|
||||||
|
|
||||||
caseFinally :: Assertion
|
|
||||||
caseFinally = do
|
|
||||||
i <- newIORef (1 :: Int)
|
|
||||||
let h = finallyHandler (do
|
|
||||||
liftIO $ writeIORef i 2
|
|
||||||
() <- redirectString RedirectTemporary ""
|
|
||||||
return ()) $ liftIO $ writeIORef i 3
|
|
||||||
let y = runHandler h undefined undefined undefined undefined undefined
|
|
||||||
_ <- unYesodApp y undefined undefined undefined
|
|
||||||
j <- readIORef i
|
|
||||||
j @?= 3
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
-- | A version of 'finally' which works correctly with short-circuiting.
|
|
||||||
finallyHandler :: GHandler s m a -> GHandler s m b -> GHandler s m a
|
|
||||||
finallyHandler (GHandler (ReaderT thing)) (GHandler (ReaderT after)) =
|
|
||||||
GHandler $ ReaderT $ \hd -> mapMEitherT (`C.finally` runMEitherT (after hd)) (thing hd)
|
|
||||||
|
|||||||
@ -33,17 +33,21 @@ import Control.Monad.Trans.State
|
|||||||
import Text.Hamlet
|
import Text.Hamlet
|
||||||
import Text.Cassius
|
import Text.Cassius
|
||||||
import Text.Julius
|
import Text.Julius
|
||||||
import Yesod.Handler (Route, GHandler)
|
import Yesod.Handler (Route, GHandler, HandlerData)
|
||||||
import Control.Applicative (Applicative)
|
import Control.Applicative (Applicative)
|
||||||
import Control.Monad.IO.Class (MonadIO)
|
import Control.Monad.IO.Class (MonadIO)
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO)
|
|
||||||
import Yesod.Internal
|
import Yesod.Internal
|
||||||
|
|
||||||
|
import Control.Monad.Invert (MonadInvertIO (..))
|
||||||
|
import Control.Monad (liftM)
|
||||||
|
|
||||||
-- | A generic widget, allowing specification of both the subsite and master
|
-- | A generic widget, allowing specification of both the subsite and master
|
||||||
-- site datatypes. This is basically a large 'WriterT' stack keeping track of
|
-- site datatypes. This is basically a large 'WriterT' stack keeping track of
|
||||||
-- dependencies along with a 'StateT' to track unique identifiers.
|
-- dependencies along with a 'StateT' to track unique identifiers.
|
||||||
newtype GWidget sub master a = GWidget (
|
newtype GWidget s m a = GWidget { unGWidget :: GWInner s m a }
|
||||||
|
deriving (Functor, Applicative, Monad, MonadIO)
|
||||||
|
type GWInner sub master =
|
||||||
WriterT (Body (Route master)) (
|
WriterT (Body (Route master)) (
|
||||||
WriterT (Last Title) (
|
WriterT (Last Title) (
|
||||||
WriterT (UniqueList (Script (Route master))) (
|
WriterT (UniqueList (Script (Route master))) (
|
||||||
@ -53,11 +57,19 @@ newtype GWidget sub master a = GWidget (
|
|||||||
WriterT (Head (Route master)) (
|
WriterT (Head (Route master)) (
|
||||||
StateT Int (
|
StateT Int (
|
||||||
GHandler sub master
|
GHandler sub master
|
||||||
)))))))) a)
|
))))))))
|
||||||
deriving (Functor, Applicative, Monad, MonadIO, MonadCatchIO)
|
|
||||||
instance Monoid (GWidget sub master ()) where
|
instance Monoid (GWidget sub master ()) where
|
||||||
mempty = return ()
|
mempty = return ()
|
||||||
mappend x y = x >> y
|
mappend x y = x >> y
|
||||||
|
instance MonadInvertIO (GWidget s m) where
|
||||||
|
newtype InvertedIO (GWidget s m) a =
|
||||||
|
InvGWidgetIO
|
||||||
|
{ runInvGWidgetIO :: InvertedIO (GWInner s m) a
|
||||||
|
}
|
||||||
|
type InvertedArg (GWidget s m) =
|
||||||
|
(Int, (HandlerData s m, ()))
|
||||||
|
invertIO = liftM (fmap InvGWidgetIO) . invertIO . unGWidget
|
||||||
|
revertIO f = GWidget $ revertIO $ liftM runInvGWidgetIO . f
|
||||||
|
|
||||||
instance HamletValue (GWidget s m ()) where
|
instance HamletValue (GWidget s m ()) where
|
||||||
newtype HamletMonad (GWidget s m ()) a =
|
newtype HamletMonad (GWidget s m ()) a =
|
||||||
|
|||||||
@ -52,7 +52,7 @@ import qualified Web.ClientSession as CS
|
|||||||
import qualified Data.ByteString.UTF8 as BSU
|
import qualified Data.ByteString.UTF8 as BSU
|
||||||
import Database.Persist
|
import Database.Persist
|
||||||
import Control.Monad.Trans.Class (MonadTrans (..))
|
import Control.Monad.Trans.Class (MonadTrans (..))
|
||||||
import Control.Monad.Attempt (Failure)
|
import Control.Failure (Failure)
|
||||||
import qualified Data.ByteString as S
|
import qualified Data.ByteString as S
|
||||||
import qualified Network.Wai.Middleware.CleanPath
|
import qualified Network.Wai.Middleware.CleanPath
|
||||||
import qualified Data.ByteString.Lazy as L
|
import qualified Data.ByteString.Lazy as L
|
||||||
|
|||||||
@ -37,13 +37,11 @@ library
|
|||||||
, clientsession >= 0.4.0 && < 0.5
|
, clientsession >= 0.4.0 && < 0.5
|
||||||
, pureMD5 >= 1.1.0.0 && < 2.2
|
, pureMD5 >= 1.1.0.0 && < 2.2
|
||||||
, random >= 1.0.0.2 && < 1.1
|
, random >= 1.0.0.2 && < 1.1
|
||||||
, control-monad-attempt >= 0.3 && < 0.4
|
|
||||||
, cereal >= 0.2 && < 0.4
|
, cereal >= 0.2 && < 0.4
|
||||||
, dataenc >= 0.13.0.2 && < 0.14
|
, dataenc >= 0.13.0.2 && < 0.14
|
||||||
, old-locale >= 1.0.0.2 && < 1.1
|
, old-locale >= 1.0.0.2 && < 1.1
|
||||||
, persistent >= 0.2.2 && < 0.3
|
, persistent >= 0.3.0 && < 0.4
|
||||||
, neither >= 0.0.0 && < 0.1
|
, neither >= 0.1.0 && < 0.2
|
||||||
, MonadCatchIO-transformers >= 0.2.2.0 && < 0.3
|
|
||||||
, data-object >= 0.3.1 && < 0.4
|
, data-object >= 0.3.1 && < 0.4
|
||||||
, network >= 2.2.1.5 && < 2.3
|
, network >= 2.2.1.5 && < 2.3
|
||||||
, email-validate >= 0.2.5 && < 0.3
|
, email-validate >= 0.2.5 && < 0.3
|
||||||
@ -51,6 +49,7 @@ library
|
|||||||
, web-routes >= 0.23 && < 0.24
|
, web-routes >= 0.23 && < 0.24
|
||||||
, xss-sanitize >= 0.2 && < 0.3
|
, xss-sanitize >= 0.2 && < 0.3
|
||||||
, data-default >= 0.2 && < 0.3
|
, data-default >= 0.2 && < 0.3
|
||||||
|
, failure >= 0.1 && < 0.2
|
||||||
exposed-modules: Yesod
|
exposed-modules: Yesod
|
||||||
Yesod.Content
|
Yesod.Content
|
||||||
Yesod.Dispatch
|
Yesod.Dispatch
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user