如何最佳处理IO布尔逻辑?

huangapple go评论141阅读模式
英文:

How to best handle IO Bool logic?

问题

我经常看到自己使用这个模式:

f x = do
  -- predicate :: a -> IO Bool
  b <- predicate x
  if b then 
    rest ()
  else
    return ()
  where
    rest () = do
      -- 执行剩下的 IO 操作

有其他人使用的去除 if then else 语句的模式吗?你如何最好地处理控制流和 IO Bool

英文:

I see myself using this pattern a lot:

f x = do
  -- predicate :: a -&gt; IO Bool
  b &lt;- predicate x
  if b then 
    rest ()
  else
    return ()
  where
    rest () = do
      -- rest of my IO operations

is there a pattern other people use to remove the if then else where clauses? How do you best work with control flow and IO Bool?

答案1

得分: 8

请看 whenunless

f x = do
  b <- predicate x
  when b $ do
    -- 其余的IO操作

extra 包中还有 whenM

英文:

Check out when and unless.

f x = do
  b &lt;- predicate x
  when b $ do
    -- rest of the IO operation

In the extra package there also is whenM.

答案2

得分: 2

除了when之外,还有一件方便的事情,与布尔值无关,可以使用-XLambdaCase和一个开放绑定操作符来避免引入变量:

{-# LANGUAGE LambdaCase #-}

f x = do
   predicate >>= \case
     True -> rest ()
     False -> return ()
  where
    rest () = do
      ...

顺便提一下,如果when的参数反转了,那么也可以按照这种方式使用:

thenfore :: m () -> Bool -> m ()
thenfore = flip when

f x = do
   predicate >>= thenfore (rest ())
  where
    rest () = do
      ...

或者,内联rest

f x = do
   predicate >>= thenfore `id` do
      ...

关于id作为操作符的使用说明:注意id :: a -> a比函数应用操作符($)更一般,所以可以以相同的方式使用它,但它具有更高的优先级,因此可以像上面所示的那样与>>=结合使用。

英文:

In additional to when, another thing that's handy – and not specific to booleans – is to use -XLambdaCase and an open bind operator to avoid having to introduce a variable:

{-# LANGUAGE LambdaCase #-}

f x = do
   predicate &gt;&gt;= \case
     True -&gt; rest ()
     False -&gt; return ()
  where
    rest () = do
      ...

Incidentally, if when had its arguments flipped then this could be used in that style too:

thenfore :: m () -&gt; Bool -&gt; m ()
thenfore = flip when

f x = do
   predicate &gt;&gt;= thenfore (rest ())
  where
    rest () = do
      ...

...or, inlining rest,

f x = do
   predicate &gt;&gt;= thenfore`id`do
      ...

Explanation on the use of id as an operator: notice that id :: a -&gt; a is strictly more general than the function-application operator ($) :: (a -&gt; b) -&gt; (a -&gt; b), so it can be used in the same way, but it has higher precedence and can thus be combined with &gt;&gt;= as done above.

huangapple
  • 本文由 发表于 2023年2月16日 15:11:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468886.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定