Я часто использую этот шаблон:
f x = do
-- predicate :: a -> IO Bool
b <- predicate x
if b then
rest ()
else
return ()
where
rest () = do
-- rest of my IO operations
Есть ли шаблон, который другие люди используют для удаления предложений if then else where? Как вам лучше всего работать с потоком управления и IO Bool?
Почему вы пишете rest () вместо просто rest или вместо then do и операций?
Потому что именно так я заставил это работать и не знал об идее then do?
Проверьте , когда и , если .
f x = do
b <- predicate x
when b $ do
-- rest of the IO operation
В пакете extra также есть whenM.
В дополнение к 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 является строго более общим, чем оператор приложения функции ($) :: (a -> b) -> (a -> b), поэтому его можно использовать таким же образом, но он имеет более высокий приоритет и, таким образом, может быть объединен с >>=, как это сделано выше. .
Возможно, связано: Как мне справиться со многими уровнями отступов?.