2

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

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

George
  • 6,927
  • 4
  • 34
  • 67

2 Answers2

5

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.

michmach
  • 61
  • 1
  • 2
4

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.

luqui
  • 59,485
  • 12
  • 145
  • 204