简体   繁体   English

使用HTTP管道时Haskell类型错误

[英]Haskell Type Error while using HTTP-Conduit

I am working on OAuth2 authentication for a Yesod application and I am having a type error that I really really don't understand. 我正在为Yesod应用程序进行OAuth2身份验证,但遇到了我真的不理解的类型错误。 The code is broken at the moment, and I have a few :: IO () 's and undefined s thrown around to help me isolate the type error, but the relevant code is: 目前,代码已损坏,并且抛出了:: IO ()undefined ,以帮助我隔离类型错误,但是相关代码为:

getAccessToken :: Manager -> OAuth2 -> ExchangeToken -> IO (OAuth2Result Errors OAuth2Token)
getAccessToken manager oa code = do

  let (uri, defaultBody) = accessTokenUrl oa code
  let body = defaultBody <> [ ("client_id", TE.encodeUtf8 . oauthClientId $ oa )
                            , ("client_secret", TE.encodeUtf8 . oauthClientSecret $ oa)
                            , ("resource", TE.encodeUtf8 . oauthClientId $ oa)
                            ]

  response <- performOAuth2PostRequest manager oa uri body

  return undefined

performOAuth2PostRequest :: Manager -> OAuth2 -> URI -> PostBody -> IO (Response ByteString)
performOAuth2PostRequest manager oa uri body  = do
  defaultReq <- uriToRequest uri

  let addBasicAuth = applyBasicAuth (TE.encodeUtf8 . oauthClientId $ oa)
                                    (TE.encodeUtf8 . oauthClientSecret $ oa)

  let req = (addBasicAuth . updateRequestHeaders Nothing) defaultReq

  (httpLbs (urlEncodedBody body req) manager) :: IO (Response ByteString)

Notice that I am specifically setting the type of the httpLbs (urlEnc...) manager action as an IO (Response ByteString) using the ScopedTypeVariables extension. 请注意,我使用ScopedTypeVariables扩展名专门将httpLbs (urlEnc...) manager操作的类型设置为IO (Response ByteString) ScopedTypeVariables Also, that line of code should be an IO action because it's being performed at the top level of an IO action. 另外,该行代码应该是IO操作,因为它是在IO操作的顶层执行的。

In fact, I ran a GHCi session and did: 实际上,我进行了GHCi会议并做了:

Network.OAuth.OAuth2.HttpClient Network.OAuth.OAuth2.Internal 
Network.HTTP.Conduit Data.Functor Prelude> :t httpLbs
httpLbs
  :: Control.Monad.IO.Class.MonadIO m =>
     Request
     -> Manager -> m (Response Data.ByteString.Lazy.Internal.ByteString)

Which confirms my understanding that httpLbs should yield a MonadIO m => m (Response ByteString) . 这证实了我的理解,即httpLbs应该产生MonadIO m => m (Response ByteString)

But here is the error I get: 但是这是我得到的错误:

• Couldn't match type ‘Response
                         Data.ByteString.Lazy.Internal.ByteString’
                 with ‘IO (Response ByteString)’
  Expected type: Manager -> IO (Response ByteString)
    Actual type: Manager
                 -> Response Data.ByteString.Lazy.Internal.ByteString
• The function ‘httpLbs’ is applied to two arguments,
  its type is ‘Request
               -> m1 (Response Data.ByteString.Lazy.Internal.ByteString)’,
  it is specialized to ‘Request
                        -> Manager -> Response Data.ByteString.Lazy.Internal.ByteString’

Why is GHC specializing m to Response instead of IO ? 为什么GHC将m专门用于Response而不是IO How do I fix it? 我如何解决它?

You haven't included your import statements, making it difficult to debug this. 您尚未包含import语句,因此很难调试它。 My best guess though is that you've imported Network.HTTP.Simple , which provides functions that do not require an explicit Manager argument. 不过,我最好的猜测是您已导入Network.HTTP.Simple ,它提供了不需要显式Manager参数的函数。 I'm guessing this from the error message providing the expected type: 我从提供预期类型的​​错误消息中猜测出这一点:

Request -> m1 (Response Data.ByteString.Lazy.Internal.ByteString)

Solution: either change the import, or drop the Manager argument. 解决方案:更改导入,或删除Manager参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM