Haskell中的“guard”不能使用“guard”来指定“Left”的特定消息吗?

Can `guard` not guards in Haskell be used to specify a particular message for `Left`

提问人:Piskator 提问时间:8/25/2023 最后编辑:Piskator 更新时间:8/26/2023 访问量:76

问:

RIO-Prelude 的函数是否提供了任何方法来确定消息的内容,如果它失败了 -Monad?例如,例如guardEither

somefun :: Either String Int
somefun =  do guard (4+2 == 8); return 2

将返回,其中 是以某种方式指定给 的字符串。Left someContentsomeContentguard

我无法根据文档找到任何方法,但如果它存在,我很乐意知道它,因为这可能是避免嵌套语句的好方法。guardif

Haskell 类型 函数式编程 单子

评论

1赞 leftaroundabout 8/25/2023
“如果消息失败了,如何决定消息的内容?”——我几乎不知道你在说什么。请详细说明。
0赞 Piskator 8/25/2023
@leftaroundabout,我试图用一个例子来说明。
0赞 willeM_ Van Onsem 8/25/2023
guard如果条件失败,则可以使用,所以不行。您应该改用“fail”,因此可以添加一些失败消息。emtpyguard
0赞 Piskator 8/25/2023
@WillemVanOnsem我该怎么做呢?

答:

3赞 willeM_ Van Onsem 8/25/2023 #1

guard如果条件失败,则可以使用,所以不行。您应该改用,因此制作一些允许添加失败消息的内容。emptyfailguard

因此,您可以使用:

{-# LANGUAGE FlexibleInstances #-}

instance MonadFail (Either String) where
    fail = Left


guard' :: MonadFail m => String -> Bool -> m ()
guard' msg = go
  where go False = fail msg
        go True = pure ()

因此,您失败了:

somefun :: Either String Int
somefun =  do guard' "arithmetic error" (4+2 == 8); return 2

我实际上很惊讶地发现这不是一个实例(感谢@JosephSible注意到这一点)。Either StringMonadFail

评论

0赞 Joseph Sible-Reinstate Monica 8/26/2023
Either String没有实例。MonadFail
0赞 willeM_ Van Onsem 8/26/2023
@JosephSible-ReinstateMonica:啊啊啊你知道为什么吗?我能想到的唯一原因是它会启用编译指示?FlexibleInstances
0赞 Joseph Sible-Reinstate Monica 8/26/2023
查看 gitlab.haskell.org/ghc/ghc/-/issues/12160
0赞 willeM_ Van Onsem 8/26/2023
@JosephSible-ReinstateMonica:有趣的是,我想知道,如果最终转向标准(因为现在很常见),他们最终是否会改变主意。主要观点似乎是关于标准Haskell的当前状态,但最终可能会改变。IsStringOverloadedStrings
3赞 leftaroundabout 8/25/2023 #2

这听起来更像是一份工作,除非when

somefun :: Either String Int
somefun = do
   unless (4+2 == 8) $ Left somecontent
   return 2

我实际上宁愿写.when (4+2 /= 8) $ Left somecontent

评论

1赞 chi 8/26/2023
在这种情况下,我可能会想写信来传达意图。Left somecontentthrowError somecontent