When acquiring, using, and releasing various resources, it can be quite convenient to write a function to manage the acquisition and releasing, taking a function of the acquired value that specifies an action to be performed in between.The function
bracket :: IO a -- computation to run first ("acquire resource") -> (a -> IO b) -- computation to run last ("release resource") -> (a -> IO c) -- computation to run in-between -> IO c
withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
withArray :: Storable a => [a] -> (Ptr a -> IO b) -> IO b
which manages the memory associated with a foreign array.
A common thing one might want to do is to collect up a list of such resource-managing with-functions and build from them a single with-function that manages the whole list of associated resources.For this one can use what is effectively
nest :: [(r -> a) -> a] -> ([r] -> a) -> a nest xs = runCont (sequence (map Cont xs))
withCStringArray0 :: [String] -> (Ptr CString -> IO a) -> IO a withCStringArray0 strings act = nest (map withCString strings) (\rs -> withArray0 nullPtr rs act)