类型具有构造函数的模式匹配

问题描述 投票:0回答:1

我正在使用具有以下类型的第三方库:

data ServicesRequest req contentType res accept = ServicesRequest
  { rMethod  :: NH.Method   
  , rUrlPath :: [BCL.ByteString] 
  , rParams   :: Params 
  , rAuthTypes :: [P.TypeRep] 
  }

我正在尝试从

req
(服务请求)列表中提取
ServicesRequest
,类似于:

let reqs = map (\(ServicesRequest req contentType res accept) -> req) serviceRequests 

不幸的是,这会生成一个

NH.Method
的列表,这是 ServiceRequest 的第一个构造函数。

我尝试了不同的变体来获取“req”,但它们都给出了“模式中的解析错误”:

let reqs = map (\(ServicesRequest{} req contentType res accept) -> req) serviceRequests 

let reqs = map (\((ServicesRequest _ _ _ _) req contentType res accept) -> req) serviceRequests 

如何在

req
上进行模式匹配而不将其与 rMethod 构造函数混淆?

haskell
1个回答
0
投票

我正在尝试从

req
 列表中提取 
ServicesRequest

req
中没有
ServicesRequest
,所以这是不可能的。

是否可以对类型进行模式匹配?

默认情况下,类型级别没有模式匹配。您当然可以编写类型来确保

req
类型与
ServicesRequest
中的类型相同 - 只需在您想要的两个地方使用相同的名称即可。例如:

constrainedId :: ServicesRequest req contentType res accept -> req -> req
constrainedId _ = id

此类受限类型可能很有用。

对于更高级的用途,类型族提供了一些看起来有点像类型级模式匹配的东西。例如:

type family ReqFromSR a where
    ReqFromSR (ServicesRequest req contentType res accept) = req

然后,您可以以稍微更紧凑的形式为

constrainedId
编写大致相同的类型:

constrainedId :: sr -> ReqFromSR sr -> ReqFromSR sr
-- OR
constrainedId :: ReqFromSR sr ~ req => sr -> req -> req
constrainedId _ = id
© www.soinside.com 2019 - 2024. All rights reserved.