Haskell Servant空路组合

时间:2017-03-24 23:52:49

标签: haskell servant

我正在写一些CRUD助手以获得乐趣和利润,而我发现自己需要空路或无路线。 mempty:>,如果愿意的话。

这是我想写的:

type Index model =
  Reassoc (QueryParams model :> Get '[JSON] (Collection model))

type family Reassoc xs where
  Reassoc ((x :> y) :> z) = Reassoc (x :> Reassoc (y :> z))
  Reassoc (x :> y) = x :> y

type family QueryParams model

type instance QueryParams User =
  MakeQueryParams '[ '("organizationId", Int) ]

这一切都归功于这个人:

type family MakeQueryParams xs where
  MakeQueryParams ( '(sym, ty) ': xs ) 
    = QueryParam sym ty :> MakeQueryParams xs
  MakeQueryParams '[] 
    = ... :(

是否有空路径组合器?

到目前为止,我已经通过在这些系列中使用next参数解决了这个问题,但对于Servant而言,它的惯用性要少得多。

type family MakeQueryParams xs next where
    MakeQueryParams '[] next =
        next
    MakeQueryParams ('(sym, ty) ': xs) next =
        QueryParam sym ty :> MakeQueryParams xs next

type Index model = QueryParams model (Get '[JSON] (Collection model))

type family QueryParams model next

type instance QueryParams User next =
    MakeQueryParams '[ '("organizationId", Int) ] next

1 个答案:

答案 0 :(得分:0)

如果您真的坚持写作

type API = QueryParams '[ '("id", Int) ] :> Get '[JSON] Bool

您将foldr这样的想法/解决方案(完全可以)与新的组合器相结合:

data QueryParams (ps :: [(Symbol, *)])

instance HasServer api ctx
  => HasServer (QueryParams '[] :> api) ctx where
    type ServerT (QueryParams '[] api) m = ServerT api m

    route = ...

instance HasServer (QueryParam sym ty :> MakeQueryParams ('(sym, ty) ': ps) api) ctx
  => HasServer (QueryParams ('(sym, ty) ': ps) api) ctx where
    type ServerT (QueryParams ('(sym, ty) ': ps) api) m = ...

    route = ...

为nil和cons案例编写单独的实例将使实例的实现更加直接。

可以认为我们必须引入新的组合器,否则我们将无法在正确的位置插入类型族。有点像我们有时需要编写newtype来编写不同的实例。