Created
April 19, 2017 12:07
-
-
Save naoto-ogawa/618c7fb22bd1412947d08ede358bd1ce to your computer and use it in GitHub Desktop.
Servant Type Transition from API to Handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE DeriveGeneric #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE GeneralizedNewtypeDeriving #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE OverloadedStrings #-} | |
{-# LANGUAGE ScopedTypeVariables #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE RecordWildCards #-} | |
import Control.Monad.IO.Class -- liftIO | |
import Control.Monad.Trans.Except -- Handler | |
import Data.Aeson.Types -- JSON | |
import Data.Aeson.Parser -- JSON | |
import GHC.Generics | |
import Network.Wai.Handler.Warp | |
import Servant | |
import Servant.Server.Internal.RoutingApplication | |
import Network.Wai | |
data MyData = A | B | C deriving (Show) | |
-- class HasServer api context where | |
-- type ServerT api (m :: * -> *) :: * | |
-- route :: Proxy api -> Context context -> Delayed env (Server api ) -> Router env | |
-- type Server (api :: k) = ServerT api Handler | |
-- | |
instance (HasServer api context) => HasServer (MyData :> api) context where | |
type ServerT (MyData :> api) m = MyData-> ServerT api m | |
route Proxy context subserver = route (Proxy :: Proxy api) context $ passToServer subserver process | |
where process req = do | |
liftIO $ print "abc" | |
case lookup "key" (queryString req) of | |
Just x -> return A | |
Nothing -> return C | |
type MyAPI = MyData :> Get '[JSON] [String] | |
div' :: MyData -> Handler [String] | |
div' mydata = do | |
liftIO $ print mydata | |
return ["Hello", "Worl"] | |
myServer :: Server MyAPI | |
myServer = div' | |
-- > :i Server | |
-- type Server (api :: k) = ServerT api Handler | |
-- | |
-- type ServerT api (m :: * -> *) :: * | |
-- | |
-- > :t myServer | |
-- myServer :: MyData -> Handler [String] | |
-- type ServerT (MyData :> api) m = MyData-> ServerT api m | |
-- | |
-- Server MyAPI | |
-- | | |
-- | def : type Server (api :: k) = ServerT api Handler | |
-- | | |
-- ServerT MyAPI (m :: Handler) -- type of m is Handler | |
-- | | |
-- | def : type MyAPI = MyData :> Get '[JSON] [String] | |
-- | | |
-- ServerT (MyData :> Get '[JSON] [String]) (m :: Handler) | |
-- | | |
-- | just replacement | |
-- | | |
-- ServerT (MyData :> api ) (m :: Handler) | |
-- | | |
-- | def : type ServerT (MyData :> api) m = MyData-> ServerT api m | |
-- | | |
-- MyData -> ServerT api ( m :: Handler) | |
-- | | |
-- | just re-replacement | |
-- | | |
-- MyData -> Server (Get '[JSON] [String]) (m :: Handler) | |
-- | | |
-- | def : type Get = Verb 'GET 200 :: [*] -> k -> * | |
-- | | |
-- MyData -> Server (Verb 'GET 200 '[JSON] [String]) (m :: Handler) | |
-- | | | |
-- | (Verb method status ctypes a ) | |
-- | | |
-- | https://hackage.haskell.org/package/servant-server-0.10/docs/src/Servant-Server-Internal.html#line-237 | |
-- | def : | |
-- | instance OVERLAPPABLE_ | |
-- | ( AllCTRender ctypes a, ReflectMethod method, KnownNat status | |
-- | ) => HasServer (Verb method status ctypes a) context where | |
-- | | |
-- | type ServerT (Verb method status ctypes a) m = m a | |
-- | | |
-- | a :: [String] | |
-- | m :: Hanlder | |
-- | | |
-- MyData -> Handler [String] | |
-- | |
-- | |
-- (cf) | |
-- div'' :: MyData -> Maybe [String] | |
-- div'' = undefined | |
-- | |
-- myServer'' :: Server MyAPI | |
-- myServer'' = div'' | |
-- | |
-- MyWebApp_myHasServer2.hs:118:14: error: | |
-- • Couldn't match type ‘Maybe [String]’ with ‘Handler [String]’ | |
-- Expected type: Server MyAPI | |
-- Actual type: MyData -> Maybe [String] | |
-- • In the expression: div'' | |
-- In an equation for ‘myServer''’: myServer'' = div'' | |
-- Failed, modules loaded: none. | |
-- | |
myProxy :: Proxy MyAPI | |
myProxy = Proxy | |
myApp :: Application | |
myApp = serve myProxy myServer | |
main :: IO () | |
main = run 8081 myApp | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment