on master help sign in
Merge pull request #736 from phadej/entered
d004805Oleg Grenrus
servant-server/src/Servant/Server.hs+3−2
@@ -207,7 +207,7 @@ layoutWithContext p context =
207-- monad. Or have your types ensure that your handlers don't do any IO. Enter
207-- monad. Or have your types ensure that your handlers don't do any IO. Enter
208-- `enter`.
208-- `enter`.
209--
209--
210−-- With `enter`, you can provide a function, wrapped in the `(:~>)` / `Nat`
210+-- With `enter`, you can provide a function, wrapped in the `(:~>)` / `NT`
211-- newtype, to convert any number of endpoints from one type constructor to
211-- newtype, to convert any number of endpoints from one type constructor to
212-- another. For example
212-- another. For example
213--
213--
@@ -215,7 +215,8 @@ layoutWithContext p context =
215-- >>> import qualified Control.Category as C
215-- >>> import qualified Control.Category as C
216-- >>> type ReaderAPI = "ep1" :> Get '[JSON] Int :<|> "ep2" :> Get '[JSON] String
216-- >>> type ReaderAPI = "ep1" :> Get '[JSON] Int :<|> "ep2" :> Get '[JSON] String
217-- >>> let readerServer = return 1797 :<|> ask :: ServerT ReaderAPI (Reader String)
217-- >>> let readerServer = return 1797 :<|> ask :: ServerT ReaderAPI (Reader String)
218−-- >>> let mainServer = enter (generalizeNat C.. (runReaderTNat "hi")) readerServer :: Server ReaderAPI
218+-- >>> let nt = generalizeNat C.. (runReaderTNat "hi") :: Reader String :~> Handler
219+-- >>> let mainServer = enter nt readerServer :: Server ReaderAPI
219--
220--
220
221
221-- $setup
222-- $setup
servant-server/test/Servant/ArbitraryMonadServerSpec.hs+2−1
@@ -5,6 +5,7 @@ module Servant.ArbitraryMonadServerSpec where
5
5
6import qualified Control.Category as C
6import qualified Control.Category as C
7import Control.Monad.Reader
7import Control.Monad.Reader
8+import Data.Functor.Identity
8import Data.Proxy
9import Data.Proxy
9import Servant.API
10import Servant.API
10import Servant.Server
11import Servant.Server
@@ -40,7 +41,7 @@ readerServer :: Server ReaderAPI
40readerServer = enter fReader readerServer'
41readerServer = enter fReader readerServer'
41
42
42combinedReaderServer' :: ServerT CombinedAPI (Reader String)
43combinedReaderServer' :: ServerT CombinedAPI (Reader String)
43−combinedReaderServer' = readerServer' :<|> enter generalizeNat (return True)
44+combinedReaderServer' = readerServer' :<|> enter (generalizeNat :: Identity :~> Reader String) (return True)
44
45
45combinedReaderServer :: Server CombinedAPI
46combinedReaderServer :: Server CombinedAPI
46combinedReaderServer = enter fReader combinedReaderServer'
47combinedReaderServer = enter fReader combinedReaderServer'
servant/src/Servant/Utils/Enter.hs+27−7
@@ -27,21 +27,41 @@ import Prelude.Compat
27
27
28import Servant.API
28import Servant.API
29
29
30−class Enter typ arg ret | typ arg -> ret, typ ret -> arg where
30+type family Entered m n api where
31+ Entered m n (m a) = n a
32+ Entered m n (a -> api) = a -> Entered m n api
33+ Entered m n (api1 :<|> api2) = Entered m n api1 :<|> Entered m n api2
34+
35+class ( Entered m n typ ~ ret
36+ , Entered n m ret ~ typ
37+ )
38+ => Enter typ m n ret
39+ where
31− enter :: arg -> typ -> ret
40+ enter :: (m :~> n) -> typ -> ret
32
41
33-- ** Servant combinators
42-- ** Servant combinators
43+
44+instance
45+ ( Entered m1 n1 (typ1 :<|> typ2) ~ (ret1 :<|> ret2)
46+ , Entered n1 m1 (ret1 :<|> ret2) ~ (typ1 :<|> typ2)
34−instance ( Enter typ1 arg1 ret1, Enter typ2 arg2 ret2
47+ , Enter typ1 m1 n1 ret1, Enter typ2 m2 n2 ret2
35− , arg1 ~ arg2
48+ , m1 ~ m2, n1 ~ n2
36− ) => Enter (typ1 :<|> typ2) arg1 (ret1 :<|> ret2) where
49+ ) => Enter (typ1 :<|> typ2) m1 n1 (ret1 :<|> ret2)
50+ where
37 enter e (a :<|> b) = enter e a :<|> enter e b
51 enter e (a :<|> b) = enter e a :<|> enter e b
38
52
39−instance (Enter b arg ret) => Enter (a -> b) arg (a -> ret) where
53+instance
54+ ( Entered m n (a -> typ) ~ (a -> ret)
55+ , Entered n m (a -> ret) ~ (a -> typ)
56+ , Enter typ m n ret
57+ )
58+ => Enter (a -> typ) m n (a -> ret)
59+ where
40 enter arg f a = enter arg (f a)
60 enter arg f a = enter arg (f a)
41
61
42-- ** Useful instances
62-- ** Useful instances
43
63
44−instance Enter (m a) (m :~> n) (n a) where
64+instance Enter (m a) m n (n a) where
45 enter (NT f) = f
65 enter (NT f) = f
46
66
47-- | Like `lift`.
67-- | Like `lift`.