How to Convert a `Shell Line` to `Text` in Haskell Turtle Library?

370 Views Asked by At

Consider (inshell "echo A line of text." empty) has type Shell Line.

Question: How can one convert a value of this type to Text?

2

There are 2 best solutions below

0
On

You can't. See the definition of Shell*.

newtype Shell a = Shell { _foldIO :: forall r . FoldM IO a r -> IO r }

You can only get IO thingies out of it. However you can probably get an IO Text, and since you're doing shell stuff I suspect you have an IO monad context hanging around.

FoldM is defined as*

data FoldM m a b =
   -- FoldM step initial extract
   forall x . FoldM (x -> a -> m x) (m x) (x -> m b)

So if we can construct a FoldM IO Line Text then we can get what we need, I suspect. Here's a guess (not typechecked, and this is getting kind of complicated so I'm probably making mistakes).

shellToText :: Shell Text -> IO Text
shellToText shell = foldIO shell foldm
    where
    foldm :: FoldM IO Line Text
    foldm = FoldM (\accum line -> return (accum <> lineToText line)) -- Text -> Line -> IO Text
                  (return Text.empty)                                -- IO Text
                  return                                             -- Text -> IO Text

This can probably be considerably simplified by using the combinators in Control.Foldl, but I'll leave that as an exercise.

(*) In case you're not familiar, the first forall indicates a rank-2 type and the second one indicates an existential type.

0
On

strict function to the rescue:

strict :: MonadIO io => Shell Line -> io Text

so, you can

strict $ inshell "echo a line of text." empty

and get the output of the shell command in the IO Text monad.