如何解析此 GHC 类型检查错误消息?
How do I parse this GHC type check error message?
我被这个 GHC(8.4.3 版)类型检查错误难住了。这是我正在处理的 Haskell 仆人代码库的摘录。如果有人可以解释此消息的原因,我将不胜感激。很抱歉代码的长度,但我无法进一步减少它。
{-# 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. ...
时,GHC 发现您想将 s
类型变量实例化为 String
,但它无法确定实例化 [=] 的内容14=] 输入变量到.
您可以通过为 claims
提供显式类型签名来解决此问题,但您必须启用 ScopedTypeVariables
扩展。您可以选择 instance of 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
?
我被这个 GHC(8.4.3 版)类型检查错误难住了。这是我正在处理的 Haskell 仆人代码库的摘录。如果有人可以解释此消息的原因,我将不胜感激。很抱歉代码的长度,但我无法进一步减少它。
{-# 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. ...
时,GHC 发现您想将 s
类型变量实例化为 String
,但它无法确定实例化 [=] 的内容14=] 输入变量到.
您可以通过为 claims
提供显式类型签名来解决此问题,但您必须启用 ScopedTypeVariables
扩展。您可以选择 instance of 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
?