Răzvan Flavius Panda
Răzvan Flavius Panda

Reputation: 22106

Haskell Turtle - getting Text output from inshellWithErr

What I tried:

main :: IO ()
main = do
  let eitherSuccessOrErrorLine = inshellWithErr "stack build" empty
  stackBuildOutput <- strict $ case eitherSuccessOrErrorLine of
    Shell (Left line)  -> line
    Shell (Right line) -> line
  putStr stackBuildOutput

Error message:

src/Main.hs:34:12: error:
    • Couldn't match expected type ‘Turtle.Shell.FoldShell
                                      (Either Turtle.Line.Line Turtle.Line.Line) r0
                                    -> IO r0’
                  with actual type ‘Either (Shell Turtle.Line.Line) b0’
    • In the pattern: Left line
      In the pattern: Shell (Left line)
      In a case alternative: Shell (Left line) -> line
   |
34 |     Shell (Left line)  -> line
   |            ^^^^^^^^^

src/Main.hs:35:12: error:
    • Couldn't match expected type ‘Turtle.Shell.FoldShell
                                      (Either Turtle.Line.Line Turtle.Line.Line) r1
                                    -> IO r1’
                  with actual type ‘Either a0 (Shell Turtle.Line.Line)’
    • In the pattern: Right line
      In the pattern: Shell (Right line)
      In a case alternative: Shell (Right line) -> line
   |
35 |     Shell (Right line) -> line
   |            ^^^^^^^^^^

Upvotes: 0

Views: 124

Answers (2)

Alex jg
Alex jg

Reputation: 995

The problem is that you're attempting to pattern match on the result of runShellWithErr. runShellWithErr does return a Shell (Left Line) (Right Line), but Shell is defined thusly:

newtype Shell a = Shell { _foldShell:: forall r . FoldShell a r -> IO r }

Which is why your pattern is failing.

Instead of trying to pattern match on the result of runShellWithErr, it's cleaner to extract the line from the Either within the Shell monad. Like this:

main :: IO ()
main = do
    let successOrErrorLine = do
        buildOutput <- inshellWithErr "stack build" empty
        return $ case buildOutput of 
            Left line -> line
            Right line -> line
    result <- strict successOrErrorLine
    putStr $ show result

Which can be done more succinctly as

main :: IO ()
main = do
    let successOrErrorLine = (either id id) <$> (inshellWithErr "stack build" empty)
    result <- strict successOrErrorLine
    putStr $ show result

Upvotes: 1

Răzvan Flavius Panda
Răzvan Flavius Panda

Reputation: 22106

Solution was to create a function:

runStackBuild :: Shell ()
runStackBuild = do
  out <- inshellWithErr "stack build" empty
  liftIO $ putStrLn $ lineToText $ bifold out

and call it from main :: IO ():

putStrLn "Starting `stack build`"
sh runStackBuild
putStrLn "Finished `stack build`"

Upvotes: 1

Related Questions