0

我使用AuthProtect来自servant的组合器:Servant.API.Experimental.Auth。那里没有太多代码,实例HasServer (AuthProtect tag)在其中,servant-server并且HasClient (AuthProtect tag)在您使用的任何服务客户端中都存在。

我为一个项目使用servant-snapservant-server一个自定义HasClient实现,obelisk其项目结构由三个 cabal 包组成:

  • 前端(由 ghcjs 编译)
  • common(由 ghcjsghc 编译)
  • 后端(由 ghc 编译)

我曾经有一个自定义实现AuthProtect以及包中的实例common。但是,由于ghcjs ,common既不能依赖servant-snap也不能依赖。snap-core

现在我将HasServer实例移到后端......没问题,对吧?错误的。一旦HasServer实例成为孤立实例,ghc 就不再正确解析我的 api 类型。就好像孤立实例根本不存在。

这是为什么?

有什么,我能做什么?

4

2 回答 2

1

实例是全球性的……理论上。实际上,为了支持单独编译,它们通过导入传播。因此,从使用它的模块导入定义实例的模块。传递地导入它就足够了——即导入一个模块,该模块导入一个模块,该模块导入定义实例的模块。

于 2021-04-25T00:28:37.880 回答
0

其中任何一个都解决了我的问题:

instance HasServer api context m => HasServer (AuthProtect "jwt" :> api) context m where
  type ServerT (AuthProtect "jwt" :> api) context m =
    String -> ServerT api context m

  hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s

  route (Proxy :: Proxy (AuthProtect "jwt" :> api)) context subserver =
    route (Proxy :: Proxy api) context (subserver `addAuthCheck` withRequest authCheck)
      where
        authCheck :: Request -> DelayedM m String
        authCheck =
          liftIO . evalSnap (pure "account info")
                            (\x -> pure $! (x `seq` ()))
                            (\f -> let !_ = f 0 in pure ())

如果出于某种原因我不想专门AuthProtect "jwt"化,我必须提供约束KnownSymbol tag

instance (KnownSymbol tag, HasServer api context m) => HasServer (AuthProtect tag :> api) context m where
  type ServerT (AuthProtect tag :> api) context m =
    String -> ServerT api context m

  hoistServerWithContext _ pc nt s = hoistServerWithContext (Proxy :: Proxy api) pc nt . s

  route (Proxy :: Proxy (AuthProtect tag :> api)) context subserver =
    route (Proxy :: Proxy api) context (subserver `addAuthCheck` withRequest authCheck)
      where
        authCheck :: Request -> DelayedM m String
        authCheck =
          liftIO . evalSnap (pure "account info")
                            (\x -> pure $! (x `seq` ()))
                            (\f -> let !_ = f 0 in pure ())
于 2021-04-25T04:19:20.417 回答