0

この関数を使用して、高レベルで Servant に変換する 1 つの例外セットを使用して API ハンドラーを実行できるようにしようとしていenterますが、型の一致に問題があります。

この最小限の定義セットを考えると、次のようになります。

-- server :: Config -> Server Routes
server :: Config -> ServerT Routes (ExceptT ServantErr IO)
server c = enter runApp (handlers c)

-- runApp :: AppM :~> Handler
runApp :: ExceptT AppErr IO :~> ExceptT ServantErr IO
runApp = Nat undefined

handlers :: Config -> ServerT Routes (ExceptT AppErr IO)
handlers = undefined

私はこのタイプのエラーで終わります:

Couldn't match type `IO' with `ExceptT ServantErr IO'
arising from a functional dependency between:
  constraint `servant-0.7.1:Servant.Utils.Enter.Enter
                (IO ResponseReceived)
                (ExceptT AppErr IO :~> ExceptT ServantErr IO)
                (IO ResponseReceived)'
    arising from a use of `enter'
  instance `servant-0.7.1:Servant.Utils.Enter.Enter
              (m a) (m :~> n) (n a)'
    at <no location info>
In the expression: enter runApp (handlers c)
In an equation for `server': server c = enter runApp (handlers c)

例外は、への呼び出しのある行から発生しenterます。参考までに、次の宣言enter:

class Enter typ arg ret | typ arg -> ret, typ ret -> arg where
  enter :: arg -> typ -> ret

instance Enter (m a) (m :~> n) (n a) where
  -- enter :: (m :~> n) -> m a -> n a

したがって、 を呼び出すとenter runApp、型が次のようになると予想されます。

enter :: (m :~> n) -> m a -> n a
enter (runApp :: m ~ ExceptT AppErr IO :~> n ~ ExceptT ServantErr IO) :: ExceptT AppErr IO a -> ExceptT ServantErr IO a

(上記でn ~ ExceptT ServantErr IOは、型の置換を説明するために使用していました)

そして実際には、私は他のコードから(私が模倣しようとしたが、どこが間違っていたのか理解していない)、次のenter runAppタイプを持っているべき/持っている必要があることを知っています:

enter runApp :: ServerT Routes (ExceptT AppErr IO a) -> ServerT Routes (ExceptT ServantErr IO a)

したがって、質問は多数あります。

  • 実際のタイプはenter runApp何ですか(ghciが私に与えるものではなく、より説明的な説明です)?
  • その(IO ResponseReceived)制約はどこから来ていますか?
  • 上記のコードを微調整して、ハンドラー全体が自然な変換を通過するようにするにはどうすればよいですか?
4

1 に答える 1