series of middleware function calls https://expressjs.com/en/5x/guide/using-middleware/ ミドルウェアが Handler -> Handler であるおかげで、 再利用可能な部品を目的に合わせて組み合わせることで大きいものを作れる
api ctx server) -- (1) API の仕様 ( 型レベルDSL で記述) type API = BasicAuth User :> "orders" :> Get '[JSON] [Order] 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 (要認証)
= do orders <- listOrders (userId user) pure orders Server _ は API 仕様を受け取って穴の型を返す 計算すると: Server API = User -> IO (Either ServerError [Order]) ユーザーを引数にとり、 Order リスト or ServerError を返す IO