api ctx server) -- (1) API の仕様 ( 型レベルDSL で記述) type API = BasicAuth User :> "orders" :> Get '[JSON] [Post] api :: Proxy API api = Proxy -- (2) サーバーの実装 server :: Server API -- サーバー実装の型は `API` から自動導出 server user = do orders <- listOrders (userId user) pure orders -- (3) 認証の中身の実装 ctx = checkBasicAuth :. ... where checkBasicAuth :: BasicAuthCheck User checkBasicAuth db = BasicAuthCheck $ (username, password) ->
:> "orders" :> Get '[JSON] [Order] GET /orders のレスポンスは Order のリスト、 application/json Basic 認証がかかっていて、ログイン成功時のユーザー情報の型が User type API 自体はリクエストハンドラの型ではない 型レベルの項で記述された DSL 構文木のようなもの
= "books" :> Get '[JSON] [Book] :<|> BasicAuth User :> ( "orders" :> Get '[JSON] [Order] :<|> "settings" :> Get '[JSON] Settings ) GET /books (認証不要) GET /orders (要認証) GET /settings (要認証) :<|> で枝を作れる
orders <- listOrders (userId user) pure orders Server _ は「API 仕様を受け取ってハンドラの型を返す」型レベルの関数っぽいもの 計算すると…… Server API = User -> IO (Either ServerError [Order]) ユーザーを引数にとり、 Order リスト or ServerError を返す IO