5

How do you extract a value out of the Shell monad?

I would like to sequence a list of commands à la bash's &&, but I would also like to extract the final ExitCode value.

Say I have the following code:

import           Turtle

type Commands = [Shell ExitCode]
run :: (MonadIO io) => Commands -> io ExitCode
run cs = whatIsThisFunction $ Prelude.foldl (.&&.) (return ExitSuccess) cs

whatIsThisFunction :: (MonadIO io) => Shell a -> io a
whatIsThisFunction = undefined

I tried to see if I could implement this with Control.Foldl, but did not find a solution.

Any ideas?

More generally, why doesn't Turtle provide a function with such signature:

sh' :: MonadIO io => Shell a -> io a 

2 Answers2

5

Turtle.Shell provides you with a fold :: MonadIO io => Shell a -> Fold a b -> io b and Control.Foldl gives you a bunch of Folds amongst which: last :: Fold a (Maybe a). You can combine the two to extract the last ExitCode your command returns like so:

import Control.Monad.IO.Class
import Turtle.Shell  as TS
import Control.Foldl as CF

sh' :: MonadIO io => Shell a -> io (Maybe a)
sh' c = TS.fold c CF.last
gallais
  • 11,823
  • 2
  • 30
  • 63
  • Thanks you! I was looking for something like this! – damien.courousse Aug 29 '17 at 20:05
  • BTW, it looks like a more idiomatic way to handle errors in Turtle is to use Exceptions. Then the code would more look like: ``` Tt.sh cmds `catches` [ Handler (\(e::Tt.ProcFailed) -> Log.error $ show e) , Handler (\(e::Tt.ShellFailed) -> Log.error $ show e) , -- etc. ] ``` Do you agree? (sorry for the bad code layout, I don't know how to do this in a comment) – damien.courousse Aug 29 '17 at 20:07
3

sh' :: MonadIO io => Shell a -> io a is not possible because Shell a may be constructed from [a] (evidenced by select :: [a] -> Shell a) which can be empty.

erisco
  • 14,154
  • 2
  • 40
  • 45
  • 1
    With `IO`, you could just make it throw. Better solution: Switch it to `io (Maybe a)`. – Reactormonk Aug 27 '17 at 18:13
  • So, when I was down-voted, is that because the answer is too short or does it contain factually incorrect information? I did not elaborate on what to do because the questioner demonstrated they already knew of `Control.Foldl`. Therefore, the question to me was only why that particular signature was not part of the library. @Reactormonk does suggest that my wording of "not possible" may be too strong. My opinion on exceptions is not much different than my opinion on `undefined`. – erisco Aug 28 '17 at 17:37