簡體   English   中英

如何解析此GHC類型檢查錯誤消息?

[英]How do I parse this GHC type check error message?

我被這個GHC(版本8.4.3)類型檢查錯誤所困擾。 這是我正在研究的Haskell Servant代碼庫的摘錄。 如果有人可以解釋此消息的原因,我將不勝感激。 對於代碼的長度,我們深表歉意,但我無法進一步減少代碼長度。

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}

module Api2 where

import Control.Lens (preview)
import Control.Lens.Cons
import Control.Monad.Error.Class
import Control.Monad.Except (runExceptT)
import Control.Monad.IO.Class (liftIO, MonadIO)
import Control.Monad.Trans.Maybe (MaybeT, runMaybeT)
import Crypto.JOSE.Compact
import Crypto.JOSE.Error
import Crypto.JWT (JWT, JWK, JWTError, verifyClaims, decodeCompact,
               defaultJWTValidationSettings, stringOrUri, ClaimsSet, 
               AsJWTError)
import Data.Aeson (decode, encode)
import Data.Aeson.Types
import Data.Maybe (fromJust)
import Data.Text as T
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Data.Word8(isSpace)
import Network.Wai (Request, requestHeaders)
import Servant.API.Experimental.Auth (AuthProtect)
import Servant.Auth.Server (FromJWT, ToJWT)
import Servant.Server.Experimental.Auth (AuthHandler, AuthServerData, 
         mkAuthHandler)
import Servant.Server.Internal.ServantErr
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as L

data User = User

authHandler :: AuthHandler Request User
authHandler = mkAuthHandler authF2

authF2 :: (MonadIO m,
       MonadError ServantErr m) =>
      Request -> m User
authF2 req = do
  case lookup "Authorization" (requestHeaders req) of
    Nothing -> throwError err401
    Just authH -> do
      let (b, rest) = BS.break isSpace authH

    if T.toLower (decodeUtf8 b) == "bearer"
      then do
        claims <- liftIO $ verifyJwt "" (L.fromStrict rest) 
                   ("audience"::String)
        return $ User
      else throwError err401

verifyJwt
  :: forall e s. (Crypto.JWT.AsJWTError JWTError, (AsError e), 
                 AsJWTError e,
              Control.Lens.Cons.Cons s s Char Char, Monoid s) =>
     FilePath
     -> L.ByteString
     -> s
     -> IO (Either e Crypto.JWT.ClaimsSet)
verifyJwt jwkFilename jwtData aud = do
  let
    aud' = fromJust $ preview stringOrUri aud
    conf = defaultJWTValidationSettings (== aud')

  Just k <-  decode <$> L.readFile jwkFilename
  result <- runExceptT
    (decodeCompact jwtData >>= verifyClaims conf (k :: JWK))
  return result

在GHC中加載此文件時,出現以下錯誤。

• Could not deduce (AsError e0) arising from a use of ‘verifyJwt’
  from the context: (MonadIO m, MonadError ServantErr m)
    bound by the type signature for:
               authF2 :: forall (m :: * -> *).
                         (MonadIO m, MonadError ServantErr m) =>
                         Request -> m User
    at servant-api-server/src/Api2.hs:(37,1)-(39,27)
  The type variable ‘e0’ is ambiguous
  These potential instances exist:
    instance AsError Crypto.JOSE.Error.Error
      -- Defined in ‘Crypto.JOSE.Error’
    instance AsError JWTError -- Defined in ‘Crypto.JWT’
• In the second argument of ‘($)’, namely
    ‘verifyJwt "" (L.fromStrict rest) ("audience" :: String)’
  In a stmt of a 'do' block:
    claims <- liftIO
                $ verifyJwt "" (L.fromStrict rest) ("audience" :: String)
  In the expression:
    do claims <- liftIO
                   $ verifyJwt "" (L.fromStrict rest) ("audience" :: String)
       return $ User
   |
48 |           claims <- liftIO $ verifyJwt "" (L.fromStrict rest) ("audience"::String)

|                              
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

當您調用verifyJwt :: forall e s. ... verifyJwt :: forall e s. ... ,GHC指出您想將s類型變量實例化為String但無法確定將e類型變量實例化為什么。

盡管必須啟用ScopedTypeVariables擴展,但可以通過為claims提供顯式類型簽名來解決此問題。 您可以選擇所需AsError實例

例如,選擇e ~ Error

authF2 :: (MonadIO m,
       MonadError ServantErr m) =>
      Request -> m User
authF2 req = do
  case lookup "Authorization" (requestHeaders req) of
    Nothing -> throwError err401
    Just authH -> do
      let (b, rest) = BS.break isSpace authH

    if T.toLower (decodeUtf8 b) == "bearer"
      then do
        (claims :: Either Error Crypto.JWT.ClaimsSet) <- liftIO $ verifyJwt ""  (L.fromStrict rest) ("audience"::String)
        return $ User
      else throwError err401

與類型錯誤無關,但是您是否還不想在返回User之前檢查claims是否不是Left

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM