2017-08-12 80 views
1

我有這樣的功能:類型類扣除錯誤

sTest :: (MonadState s m, MonadError e m) => m() 
sTest = do 
    s <- get 
    throwError "abc" 
    put s 

編譯時,我得到一個類型類扣除錯誤:如果我改變throwError拋出Int代替

• Could not deduce (MonadError [Char] m) 
    arising from a use of ‘throwError’ 
    from the context: (MonadState s m, MonadError e m) 
    bound by the type signature for: 
       sTest :: (MonadState s m, MonadError e m) => m() 
    at ... 
• In a stmt of a 'do' block: throwError "abc" 
    In the expression: 
    do { s <- get; 
     throwError "abc"; 
     put s } 
    In an equation for ‘sTest’: 
     sTest 
     = do { s <- get; 
       throwError "abc"; 
       put s } 

(並添加約束條件),則編譯成功:

sTest :: (Num e, MonadState s m, MonadError e m) => m() 
sTest = do 
    s <- get 
    throwError 123 
    put s 

任何人都可以解釋我嗎?

更新#1

我創建了錯誤一種新的類型:

data EvalError = VarNotFound 
    | PlusParamsMustBeIntVal 
    | FirstAppParamMustBeFunVal 
    | OtherError String 
    deriving (Show) 

instance Error EvalError where 
    strMsg = OtherError 

sTest :: (Error e, MonadState s m, MonadError e m) => m() 
sTest = do 
    s <- get 
    throwError $ OtherError "abc" 
    put s 

但是編譯依然沒有成功:

• Could not deduce (MonadError EvalError m) 
    arising from a use of ‘throwError’ 
    from the context: (Error e, MonadState s m, MonadError e m) 
    bound by the type signature for: 
       sTest :: (Error e, MonadState s m, MonadError e m) => m() 
    at ... 
• In a stmt of a 'do' block: throwError $ OtherError "abc" 
    In the expression: 
    do { s <- get; 
     throwError $ OtherError "abc"; 
     put s } 
    In an equation for ‘sTest’: 
     sTest 
     = do { s <- get; 
       throwError $ OtherError "abc"; 
       put s } 
+0

要拋出'123',你需要'e'爲Num。你需要什麼來拋出''abc''? – amalloy

+0

我有一個'ExceptT String m',即有'String'表示的錯誤,所以我需要拋出'String'。如果我使用如下顯式類型寫下簽名:'ExceptT String(StateT L.ByteString Identity)()',則編譯成功。但我想在這裏有點多態。有可能的? –

回答

3
throwError :: MonadError e m => e -> m a 

這裏throwError "abc"品牌e等於String,所以你需要MonadError String m

sTest :: (MonadState s m, MonadError String m) => m() 
+0

我收到此錯誤: •約束中的非類型變量參數:MonadError字符串m (使用FlexibleContexts以允許此操作) •在簽名類型中: sTest ::(MonadState sm,MonadError String m)=> m () –

+0

是的,這需要'FlexibleContexts'擴展,這是良性的。 –

+0

Yah,^^。但是如果我想堅持e的通用性,我還應該做些什麼? –