2017-08-12 65 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的通用性,我还应该做些什么? –