如何使用显式模式匹配修复 MonadFail(任一字符串)错误

How to fix the MonadFail (Either String) Error using explicit pattern matching

我试图改编一个旧的 Haskell 项目,它现在与最新的 GHC 不兼容(MonadFail 现在是默认的)。

applyCosPass :: CosCtx a => (a -> QueryExpr -> Either String QueryExpr)
                  -> a -> QueryExpr -> Either String QueryExpr
applyCosPass p c (UnionAll q1 q2) =
  UnionAll <$> applyCosPass p c q1 <*> applyCosPass p c q2
applyCosPass p c (Select sl f w g d) =
     do (Select sl' f' w' g' d') <- p c (Select sl f w g d)
     nsl <- (checkListErr $ map convSI sl')
     nf <- newFr f'
     nw <- newWh w'
     return $ Select nsl nf nw g' d'
  where ...

它returns错误如下:

• Could not deduce (MonadFail (Either String))
        arising from a do statement
        with the failable pattern ‘(Select sl' f' w' g' d')’
      from the context: CosCtx a
        bound by the type signature for:
                   applyCosPass :: forall a.
                                   CosCtx a =>
                                   (a -> QueryExpr -> Either String QueryExpr)
                                   -> a -> QueryExpr -> Either String QueryExpr
        at src/CosetteParser.lhs:(648,3)-(649,63)
    • In a stmt of a 'do' block:
        (Select sl' f' w' g' d') <- (case slstmt of
                                       Left s -> error s
                                       Right e -> Right e)

根据 Haskell Wiki 中的选项 2“Adapting New Code”,代码已修改为显式模式匹配,但错误仍然存​​在。这里可能缺少什么?

applyCosPass p c (Select sl f w g d) =
     do {(Select sl' f' w' g' d') <- (case slstmt of
                                Left s -> error s
                                Right e -> Right e);
     nsl <- (checkListErr $ map convSI sl');
     nf <- newFr f';
     nw <- newWh w';
     return $ Select nsl nf nw g' d'}
  where slstmt = p c (Select sl f w g d)

它们的意思是这样的显式模式匹配:

applyCosPass :: CosCtx a => (a -> QueryExpr -> Either String QueryExpr)
                 -> a -> QueryExpr -> Either String QueryExpr
applyCosPass p c (UnionAll q1 q2) =
  UnionAll <$> applyCosPass p c q1 <*> applyCosPass p c q2
applyCosPass p c (Select sl f w g d) = do
     slstmt <- p c (Select sl f w g d)
     case slstmt of
       Select sl' f' w' g' d' -> do
         nsl <- (checkListErr $ map convSI sl')
         nf <- newFr f'
         nw <- newWh w'
         return $ Select nsl nf nw g' d'
       ... other cases -> error "Pattern match failed" -- Boooo
  where ...

do 符号中 <- 箭头的左侧不应保留任何模式匹配。

请注意,您应该检查 Select ... 是否真的是这里唯一可能的情况,否则您可能应该处理其他情况。