Gabriella439 / turtle

Shell programming, Haskell style
BSD 3-Clause "New" or "Revised" License
943 stars 90 forks source link

How can I thread a directory created with mktempdir through multiple functions #442

Closed ParetoOptimalDev closed 1 year ago

ParetoOptimalDev commented 1 year ago

Given:

main :: IO ()
main = (Turtle.sh $ do
  tmpDir       <- Turtle.mktempdir "/tmp" "turtle"
  useTmpDir1 tmpDir
  useTmpDir2 tmpDir
  Turtle.die "we're done")

useTmpDir1 tmpDir = do
  putStrLn "useTmpDir1"
  Turtle.cd tmpDir

useTmpDir2 tmpDir = do
  putStr "useTmpDir2"
  Turtle.cd tmpDir

I get:

λ> main
useTmpDir1
useTmpDir2*** Exception: getCurrentDirectory:getWorkingDirectory: does not exist (Current working directory no longer exists)

I've re-read https://hackage.haskell.org/package/managed-1.0.9/docs/Control-Monad-Managed.html a few times and tried envisioning what the above code would look like in terms of something like:

main =
    withFile "inFile.txt" ReadMode $ \inHandle ->
        withFile "outFile.txt" WriteMode $ \outHandle ->
            copy inHandle outHandle

But it's just not clicking for whatever reason.

Can anyone tell me how I should ensure the two helper functions stay within the scope of that Managed resource and if it's not too much to ask, what it'd look like in nested form?

ParetoOptimalDev commented 1 year ago

Continuing to try and figure this out for myself...

I can't quite understand it that way because the scope of Managed doesnt stay alive through multiple functions but using the with pattern it would.

For instance:

main :: IO ()
main =
    withFile "inFile.txt" ReadMode $ \inHandle ->
            useHandle1 inHandle
            useHandle2 inHandle

useHandle1 handle = do
  putStrLn "pretend this is writing to handle"

useHandle2 handle = do
  putStrLn "pretend this is writing to handle"

I think then I'll want to somehow follow this documentation:

If you need to acquire a resource for a long-lived loop, you can instead acquire the resource first and run the loop in IO, using either of the following two equivalent idioms:

with resource (\r -> forever (useThe r))

do r <- resource
   liftIO (forever (useThe r))
ParetoOptimalDev commented 1 year ago

I tried code following that last piece of documentation and it didn't seem to help here:

-- doesn't work
try1 = (Turtle.sh $ do
  tmpDir <- Turtle.mktempdir "/tmp" "turtle"
  liftIO $ useTmpDir1 tmpDir
  liftIO $ useTmpDir2 tmpDir)

-- doesn't work
try2 = 
  let tmpDir = Turtle.mktempdir "/tmp" "turtle"
  in Turtle.with tmpDir $ \d -> do
    useTmpDir1 d
    useTmpDir2 d
ParetoOptimalDev commented 1 year ago

Another thing to try I could think of:

try3 = Turtle.runManaged $ do
  tmpDir <- Turtle.mktempdir "/tmp" "turtle"
  useTmpDir1 tmpDir
  useTmpDir2 tmpDir
ParetoOptimalDev commented 1 year ago

Given that the liftio example from try1 exists in the dhall codebase I'm assuming that this not working has more to do with me using ghci an dthings will work fine if I just run the binary.

ParetoOptimalDev commented 1 year ago

It does, closing this.