为什么参数可以接受类型类的任何构造,但它的值不能有条件地构造?
Why can a parameter accept any construction of a typeclass but its value can't be constructed conditionally?
我是 Haskell 的新手,虽然不是编程,但我一直在使用 req library 执行 HTTPS 请求。
为了保持通用性,将有两种类型的请求 - 一种是创建文档(通过 HTTP POST),另一种是更新文档(通过 HTTP PATCH,使用非空updateMask
参数中的幺半群。
我可以从 updateMask == mempty
推断出 HTTP 动词,但这不会编译,因为 POST
and PATCH
are different data
declarations (although both are valid as the first parameter of req
because they are instances of HttpMethod
.
getSaveEventRequestResponse :: Text -> Option Https -> Document -> IO IgnoreResponse
getSaveEventRequestResponse authToken updateMask document =
runReq defaultHttpConfig $
req
(if updateMask == mempty
then POST
else PATCH)
(https "test.example.com" /: "api" /: "projects" /: "myproject")
(ReqBodyJson document)
ignoreResponse $
oAuth2Bearer (encodeUtf8 authToken) <> updateMask
如果我将 if
条件替换为 POST
或 PATCH
中的任何一个,代码编译时不会出错。
有没有办法让编译器允许这个条件响应,或者我是否必须复制这个函数,一个使用 POST
变体,另一个使用 PATCH
?
编辑 以造福任何来到这里并尝试使用相同代码的人:
我使用的条件(updateMask == mempty
)在这里实际上无效,但这与问题无关。如果将此条件替换为 True
或 False
.
则问题成立
编辑 2 关于链接的问题。虽然我现在已经得到答案,但看到它的联系有多紧密,它依赖于已经考虑过部分应用。虽然原理是一样的,但部分应用的引入使得 Haskell 的初学者很难将那里的答案应用到这个上下文中。
一个可能的解决方案是使用
(if updateMask == mempty then req POST else req PATCH) other args here
这是因为
req :: (MonadHttp m, HttpMethod method, HttpBody body,
HttpResponse response,
HttpBodyAllowed (AllowsBody method) (ProvidesBody body))
=> method
-> Url scheme
-> body
-> Proxy response
-> Option scheme
-> m response
现在,AllowsBody POST
和 AllowsBody PATCH
是相等的,因为它们都被定义为 'CanHaveBody
。因此,req POST
和 req PATCH
可以共享一个公共类型:
req POST, req PATCH
:: (MonadHttp m, HttpBody body,
HttpResponse response,
HttpBodyAllowed 'CanHaveBody (ProvidesBody body))
=> Url scheme
-> body
-> Proxy response
-> Option scheme
-> m response
类型相同,可以在同一个if then else
的两个分支中使用。
我是 Haskell 的新手,虽然不是编程,但我一直在使用 req library 执行 HTTPS 请求。
为了保持通用性,将有两种类型的请求 - 一种是创建文档(通过 HTTP POST),另一种是更新文档(通过 HTTP PATCH,使用非空updateMask
参数中的幺半群。
我可以从 updateMask == mempty
推断出 HTTP 动词,但这不会编译,因为 POST
and PATCH
are different data
declarations (although both are valid as the first parameter of req
because they are instances of HttpMethod
.
getSaveEventRequestResponse :: Text -> Option Https -> Document -> IO IgnoreResponse
getSaveEventRequestResponse authToken updateMask document =
runReq defaultHttpConfig $
req
(if updateMask == mempty
then POST
else PATCH)
(https "test.example.com" /: "api" /: "projects" /: "myproject")
(ReqBodyJson document)
ignoreResponse $
oAuth2Bearer (encodeUtf8 authToken) <> updateMask
如果我将 if
条件替换为 POST
或 PATCH
中的任何一个,代码编译时不会出错。
有没有办法让编译器允许这个条件响应,或者我是否必须复制这个函数,一个使用 POST
变体,另一个使用 PATCH
?
编辑 以造福任何来到这里并尝试使用相同代码的人:
我使用的条件(updateMask == mempty
)在这里实际上无效,但这与问题无关。如果将此条件替换为 True
或 False
.
编辑 2 关于链接的问题。虽然我现在已经得到答案,但看到它的联系有多紧密,它依赖于已经考虑过部分应用。虽然原理是一样的,但部分应用的引入使得 Haskell 的初学者很难将那里的答案应用到这个上下文中。
一个可能的解决方案是使用
(if updateMask == mempty then req POST else req PATCH) other args here
这是因为
req :: (MonadHttp m, HttpMethod method, HttpBody body,
HttpResponse response,
HttpBodyAllowed (AllowsBody method) (ProvidesBody body))
=> method
-> Url scheme
-> body
-> Proxy response
-> Option scheme
-> m response
现在,AllowsBody POST
和 AllowsBody PATCH
是相等的,因为它们都被定义为 'CanHaveBody
。因此,req POST
和 req PATCH
可以共享一个公共类型:
req POST, req PATCH
:: (MonadHttp m, HttpBody body,
HttpResponse response,
HttpBodyAllowed 'CanHaveBody (ProvidesBody body))
=> Url scheme
-> body
-> Proxy response
-> Option scheme
-> m response
类型相同,可以在同一个if then else
的两个分支中使用。