Skip to content

Instantly share code, notes, and snippets.

@naoto-ogawa
Created April 19, 2017 12:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save naoto-ogawa/618c7fb22bd1412947d08ede358bd1ce to your computer and use it in GitHub Desktop.
Save naoto-ogawa/618c7fb22bd1412947d08ede358bd1ce to your computer and use it in GitHub Desktop.
Servant Type Transition from API to Handler
{-# 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