Is there a turtle function or other Haskell abstraction for joining commands using .&&

131 Views Asked by At

I have the following piece of code:

foldM (\exitCode args -> pure exitCode .&&. someCmdWith args) ExitSuccess argss

Which uses turtle's (.&&.) operator.

Is there a better abstraction I could use to apply .&&. to the results of applying someCmdWith to argss?

2

There are 2 best solutions below

0
On BEST ANSWER

Would this work?

runCmds argss = foldr (.&&.) (pure ExitSuccess) (fmap someCmdWith argss)

If you want to write it even shorter, I believe this would also work:

runCmds = foldr (.&&.) (pure ExitSuccess) . fmap someCmdWith
0
On

(.&&.) looks associative and there seems to be a neutral element (pure ExitSuccess) so let's define a Monoid:

newtype UntilFailure = UntilFailure { runUntilFailure :: IO ExitCode }

instance Monoid UntilFailure where
     mappend (UntilFailure a1) (UntilFailure a2) =  UntilfFailure (a1 .&&. a2)
     mempty = UntilFailure (pure ExitSuccess)

Then we can write stuff like:

runUntilFailure . foldMap UntilFailure $ someCmdWith <$> argss

The nice thing about defining a Monoid is that we don't have to remember which is the neutral element every time we fold a list of items, as it comes "baked in the type", so to speak.

I don't think one can define a monoid out of (.||.) however, because the neutral element would have to somehow preserve the exit code of the previous command. One could still define a Semigroup, though.