我正在使用具有以下类型的第三方库:
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 构造函数混淆?
我正在尝试从
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