How to safely `mapM` over `System.IO.openFile` - haskell

My application needs to have several resources open during runtime. I am achieving this by mapping over openFile once at the start of the application.
let filePaths = ["/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2"]
fileHandles <- mapM (`openFile` ReadWriteMode) filePaths
This code is not safe as it might work for the first 2 file paths but then throw an exception when opening the 3rd file path. In that case i need to close the first 2 file paths that were opened already so i can exit the function without leaking resources. i have looked at the functions and patterns from Control.Exception but not found anything that helps in this case. I have not looked at ResourceT yet. Does it help in this situation?
I think i am looking for a function signature that is similar to this:
safeMapM:: [a] -> (a -> IO b) -> (b -> IO()) -> [b]
where (b -> IO()) is the clean up function that is called when some exception occurred.
Solutions i could think of that are probably not good:
wrapping each element in a Maybe. Exceptions can be catched and result in a Nothing. the mapM could always finish and i could check for Nothing/Exception afterwards and then close all successfully opened file handles by their Just Handle.
using fold instead of map. when an exception at the current element occurs i can close the file handles of all previous elements of the fold and then rethrow the exception to stop the fold from continuing.

If I understand correctly, the problem is how to ensure safe closing of all handles when an exception happens.
For a single file, the usual way of ensuring safety is withFile. The complication here is that you want to open a sequence of files.
Perhaps we could write this auxiliary function that performs nested allocations of withFile and passes the list of Handles to a callback in the innermost level:
nestedWithFile :: [FilePath] -> IOMode -> ([Handle] -> IO r) -> IO r
nestedWithFile filePaths mode callback = go [] filePaths
where
go acc [] =
callback acc -- innermost invocation, protected by the withFiles
go acc (p : ps) =
withFile p mode (\handle -> go (acc ++ [handle]) ps)
Another way of doing it begins by realizing that we are doing something with a replicateM flavor: we are performing an "effect" n times, and returning a list with the results. But what would be the "effect" (that is, the Applicative) here? It seems to be "protecting the allocation of a resource with a wrapper function that ensures release".
This kind of effect seems to require some control over the "rest of the computation", because when the "rest of the computation" finishes in any way, the finalizer must still be run. This points us to the continuation monad transformer, ContT:
import Control.Monad
import Control.Monad.Trans.Cont
import System.IO
openFile' :: FilePath -> ContT r IO Handle
openFile' filePath = ContT (withFile filePath ReadWriteMode)
openSameFileSeveralTimes :: Int -> FilePath -> ContT r IO [Handle]
openSameFileSeveralTimes count filePath = replicateM count (openFile' filePath)
-- The handles are freed when the ([Handle] -> IO r) callback exits
useHandles :: ContT r IO [Handle] -> ([Handle] -> IO r) -> IO r
useHandles = runContT
The continuation transformer might be a bit too general for this purpose. There are libraries like managed which follow the same basic mechanism but are more focused on resource handling.

Related

Is it possible to use writeFile inside out of the main function (in haskell)?

I am still a beginner in Haskell, so after reading some writefile tutorials online, I see most of the writefile examples online are used inside the main function (main = IO ())
I am wondering whether it's possible to write a function that writes the results into a file using writefile when it is computed? In some programs (especially games), users might want to stop at a particular points of the game by saving the contents into a .txt file.
For example something like this: (this function does not work, just wondering how to make it work)
concat :: FilePath -> [[a]] -> [a]
concat txt [] = []`
concat txt (xs : xss) = do
y <- xs ++ concat xss
writeFile txt (unlines y)
Thanks:)
The writeFile function has the type FilePath -> String -> IO (), which means that it must run in the IO context.
It doesn't have to run in the main function, but any function that involves IO, including writeFile, will have a return type that involves IO. So you could definitely do something like this:
myFunc :: String -> IO ()
myFunc contents = do
-- do something else
writeFile "foo.txt" contents
-- do more stuff here
You can't, however, call functions that return IO a from pure functions (or, rather, you can't extract the value from the IO container). That's by design; it's how Haskell works, and it's a good thing. If you want to enable users to perform impure actions at arbitrary times, you must design for such a feature. Here's my introduction to pure interactions - that's one place to start.
Yes, you can use writeFile in other places than main, but for a place to qualify, the type IO has to be a part of that place's type signature. (The reason I'm saying place is because main isn't a function, but your concat is a function. And the place you want to look at putting your writeFile call has to be an IO action, which can be the result of a function or not.)
You mentioned saving something related to a game into a .txt file. An example of that could be:
saveGame :: FilePath -> GameState -> IO ()
saveGame gameFile gameState =
writeFile gameFile (serializeGame gameState)
serializeGame :: GameState -> String
serializeGame (GameState ...) = ...
runGame :: GameState -> IO ()
runGame gameState = do
...
if wantsToSaveGame
then saveGame gameFile gameState
else ...
...
runGame updatedGameState
main :: IO ()
main = do
...
runGame initialGameState
In this contrived example, serializeGame would not be a suitable place to call saveGame because it's a pure function, whereas runGame is a self-recursive IO () action capable of affecting files on your file system.
An example of a related IO action that isn't a function could be this one:
resetSaveGame :: IO ()
resetSaveGame =
saveGame defaultGameFile initialGameState

Is h a handle or a lambda function (or both)?

I am looking at a simple IO program from the Haskell Wikibook. The construction presented on that page works just fine, but I'm trying to understand "how".
The writeChar function below takes a filepath (as a string) and a character, and it writes the character to the file at the given path. The function uses a bracket to ensure that the file opens and closes properly. Of the three computations run in the bracket, the "computation to run in-between"---as I understand it---is a lambda function that returns the result of hPutChar h c.
Now, hPutChar itself has a declaration of hPutChar :: Handle -> Char -> IO (). This is where I'm lost. I seem to be passing h as the handle to hPutChar. I would expect a handle somehow to reference the file opened as fp, but instead it appears to be recursively calling the lambda function \h. I don't see how this lambda function calling itself recursively knows to write c to the file at fp.
I would like to understand why the last line of this function shouldn't read (\h -> hPutChar fp c). Attempting to run it that way results in "Couldn't match type ‘[Char]’ with ‘Handle’" which I consider sensible given that hPutChar expects a Handle datatype as opposed to a string.
import Control.Exception
writeChar :: FilePath -> Char -> IO ()
writeChar fp c =
bracket
(openFile fp WriteMode)
hClose
(\h -> hPutChar h c)
Let's have a look at the type of bracket (quoted as it appears in your Haskell Wiki link):
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
In your use case, the first argument, openFile fp WriteMode is an IO Handle value, a computation that produces a handle corresponding to the fp path. The third argument, \h -> hPutChar h c, is a function that takes a handle and returns a computation that writes to it. The idea is that the function you pass as the third argument specifies how the resource produced by the first argument will be used.
There is no recursion going on here. h is indeed a Handle. If you've programmed in C, the rough equivalent is a FILE. The handle consists of a file descriptor, buffers, and whatever else is needed to perform I/O on the attached file/pipe/terminal/whatever. openFile takes a path, opens the requested file (or device), and provides a handle that you can use to manipulate the requested file.
bracket
(openFile fp WriteMode)
hClose
(\h -> hPutChar h c)
This opens the file to produce a handle. That handle is passed to the third function, which binds it to h and passes it to hPutChar to output a character. Then in the end, bracket passes the handle to hClose to close the file.
If exceptions didn't exist, you could implement bracket like this:
bracket
:: IO resource
-> (resource -> IO x)
-> (resource -> IO a)
-> IO a
bracket first last middle = do
resource <- first
result <- middle resource
last resource
pure result
But bracket actually has to install an exception handler to endure that last is called even if an exception occurs.
hPutChar :: Handle -> Char -> IO ()
is a pure Haskell function, which, given two arguments h :: Handle and c :: Char, produces a pure Haskell value of type IO (), an "IO action":
h :: Handle c :: Char
---------------------------------------------
hPutChr h c :: IO ()
This "action" is simply a Haskell value, but when it appears inside the IO monad do block under main, it becomes executed by the Haskell run-time system and then it actually performs the I/O operation of putting a character c into a filesystem's entity referred to by the handle h.
As for the lambda function, the actual unambiguous syntax is
(\ h -> ... )
where the white space between \ and h is optional, and the whole (.......) expression is the lambda expression. So there is no "\h entity":
(\ ... -> ... ) is the lambda-expression syntax;
h in \ h -> is the lambda function's parameter,
... in (\ h -> ... ) is the lambda function's body.
bracket calls the (\h -> hPutChar h c) lambda function with the result produced by (openFile fp WriteMode) I/O computation, which is the handle of the file name referred to by fp, opened according to the mode WriteMode.
Main thing to understand about the Haskell monadic IO is that "computation" is not a function: it is the actual (here, I/O) computation performing the actual file open -- which produces the handle -- which is then used by the run-time system to call the pure Haskell function (\ h -> ...) with it.
This layering (of pure Haskell "world" and the impure I/O "world") is the essence of .... yes, Monad. An I/O computation does something, finds some value, uses it to call a pure Haskell function, which creates a new computation, which is then run, feeds its results into the next pure function, etc. etc.
So we keep our purity in Haskell by only talking about the impure stuff. Talking is not doing.
Or is it?

Streaming of a resource with proper acquisition and release

This is a question about the Haskell streaming library.
Stream (Of a) m r is a "stream of individual Haskell values derived from actions in some monad m and returning a value of type r". Streaming.Prelude defines many useful functions that allow nice streaming applications:
import qualified Streaming.Prelude as S
S.print $ do
S.yield "a"
S.yield "b"
S.yield "c"
The tutorial is good for getting started.
Now, the particular issue at hand is how to use this framework with a monad that requires careful instantiation and release of resources. The streaming-with package seems to be the right candidate, it has a function
bracket :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
that acquires (m a), releases (a->m c) and uses (a->m b) a resource. All three actions are encapsulated in the returned m b. withFile is a good example for how to use this:
withFile :: FilePath -> IOMode -> (Handle -> m r) -> m r
withFile fp md = bracket (liftIO (openFile fp md)) (liftIO . hClose)
Acquisition and release of the handle are nicely sandwiching the usage Handle->m r.
But: I absolutely do not see how this should be used with Stream (Of a) m r. I have to provide an a->m b and I get a m b. How is this supposed to be connected so that I obtain a Stream?
To figure this out, let's play with withFile:
import System.IO
use :: Handle -> IO (S.Stream (Of String) IO ())
use = return . S.repeatM . hGetLine
main :: IO ()
main = do
str <- S.withFile "input.dat" ReadMode use
S.print str
but that results in hGetLine: illegal operation (handle is closed). That actually makes sense, by the time S.print str is called withFile has already acquired and released the handle.
So let's move the stream consumption inside the use function:
use :: Handle -> IO ()
use h = do
S.print $ S.repeatM (hGetLine h)
and that gives a hGetLine: invalid argument (invalid byte sequence). I'm not quite sure what this error means. An isEOFError would be acceptable, but 'invalid byte sequence'? In any case, this doesn't work either.
I'm running out of ideas... How is this done?
The withFile is just a toy example, the question is really about how to correctly create and consume a stream inside a bracket.
let's move the stream consumption inside the use function
This is indeed the right approach.
I'm actually getting a proper hGetLine: end of file when running the example code. The problem is that S.repeatM (hGetLine h) never bothers to check if it has reached then end of the file, and throws an exception when it bumps into it.
The following definition of use doesn't have that problem:
use :: Handle -> IO ()
use h = do
S.print $ S.untilRight $ do eof <- System.IO.hIsEOF h
if eof then Right <$> pure ()
else Left <$> hGetLine h
It uses the untilRight function.

Haskell do clause with multiple monad types

I'm using a graphic library in Haskell called Threepenny-GUI. In this library the main function returns a UI monad object. This causes me much headache as when I attempt to unpack IO values into local variables I receive errors complaining of different monad types.
Here's an example of my problem. This is a slightly modified version of the standard main function, as given by Threepenny-GUI's code example:
main :: IO ()
main = startGUI defaultConfig setup
setup :: Window -> UI ()
setup w = do
labelsAndValues <- shuffle [1..10]
shuffle :: [Int] -> IO [Int]
shuffle [] = return []
shuffle xs = do randomPosition <- getStdRandom (randomR (0, length xs - 1))
let (left, (a:right)) = splitAt randomPosition xs
fmap (a:) (shuffle (left ++ right))
Please notice the fifth line:
labelsAndValues <- shuffle [1..10]
Which returns the following error:
Couldn't match type ‘IO’ with ‘UI’
Expected type: UI [Int]
Actual type: IO [Int]
In a stmt of a 'do' block: labelsAndValues <- shuffle [1 .. 10]
As to my question, how do I unpack the IO function using the standard arrow notation (<-), and keep on having these variables as IO () rather than UI (), so I can easily pass them on to other functions.
Currently, the only solution I found was to use liftIO, but this causes conversion to the UI monad type, while I actually want to keep on using the IO type.
A do block is for a specific type of monad, you can't just change the type in the middle.
You can either transform the action or you can nest it inside the do. Most times transformations will be ready for you. You can, for instance have a nested do that works with io and then convert it only at the point of interaction.
In your case, a liftIOLater function is offered to handle this for you by the ThreePennyUI package.
liftIOLater :: IO () -> UI ()
Schedule an IO action to be run later.
In order to perform the converse conversion, you can use runUI:
runUI :: Window -> UI a -> IO a
Execute an UI action in a particular browser window. Also runs all scheduled IO action.
This is more an extended comment - it doesn't address the main question, but your implementation of shufffle. There are 2 issues with it:
Your implementation is inefficient - O(n^2).
IO isn't the right type for it - shuffle has no general side effects, it just needs a source of randomness.
For (1) there are several solutions: One is to use Seq and its index, which is O(log n), which would make shuffle O(n log n). Or you could use ST arrays and one of the standard algorithms to get O(n).
For (2), all you need is threading a random generator, not full power of IO. There is already nice library MonadRandom that defines a monad (and a type-class) for randomized computations. And another package already provides the shuffle function. Since IO is an instance of MonadRandom, you can just use shuffle directly as a replacement for your function.
Under the cover, do is simply syntactic sugar for >>= (bind) and let:
do { x<-e; es } = e >>= \x -> do { es }
do { e; es } = e >> do { es }
do { e } = e
do {let ds; es} = let ds in do {es}
And the type of bind:
(>>=) :: Monad m => a -> (a -> m b) -> m b
So yeah it only "supports" one Monad

Haskell: How to write interactive interpreter on top of a State monad?

We're working on a model filesystem that uses a state monad internally. We have a type class with operations like these:
class Monad m => FS m where
isDirectory :: Path -> m Bool
children :: Path -> m [Path]
...
We're working on a little interactive interpreter that will offer commands like cd, ls, cat, and so on. An operation in the interpreter can be written this way:
fsop :: FS m => Operation -> m Response
The definitions of Operation and Response aren't important; if you like, take them to be strings.
The problem I am trying to solve is to write a top-level loop in the I/O monad that interprets filesystem Operations and prints responses. If IO were an instance of FS (that is, if we were working directly with the IO monad), life would be simple: we could write
loop :: Path -> IO ()
loop currentDir = do
op <- getLine
case read op of
ChangeDir d -> loop d -- should test 'isDirectory d', but let's not
Ls -> do { files <- children currentDir
; mapM_ putStrLn files
; loop currentDir }
Exit -> return ()
But that's not what I want. I want to use Control.Monad.State:
newtype Filesystem a = Filesystem (State (Data.Map.Map Path Contents) a)
and to declare
instance Monad Filesystem ...
instance FS Filesystem ...
Using the FS abstraction, I can write a single-step function that should work with any instance, and indeed the following code compiles:
step :: FS fs => Path -> Operation -> fs (Path, Response)
step currentDir op =
case op of
ChangeDir d -> return (d, "")
Ls -> do { files <- children currentDir
; return (currentDir, unlines files) }
At this point I am totally stuck. What I want to do is write an interactive loop in the IO monad, which can read Operations and print Responses, but which works on a state monad that is not necessarily IO. (One of the reasons for having a model that is not in IO is that so we can test QuickCheck properties.)
I feel like this has to be a standard problem—an interactive read-eval-print loop on top of a stateful abstraction that is not IO—but I must be missing something breathtakingly obvious because I can't seem to figure it out. I've looked online but have not been enlightened.
Any help writing an interactive, IO-performing computation that can call step would be greatly appreciated.
What about using monad transformers? They are more or less standard way to combine monads. Here an simplistic example:
type Foo a = StateT String IO a
replT :: Foo ()
replT = do
str <- liftIO getLine
state <- get
liftIO $ putStrLn ("current state: " ++ state)
liftIO $ putStrLn ("setting state: " ++ str)
put str
replT
Below are results of running replT from within ghci.
*Main> runStateT replT "Initial state"
asd
current state: Initial state
setting state: asd
zxc
current state: asd
setting state: zxc
asdasd
There are three monad transformers libs. mtl, transformers and monadLib. I cannot recommend any of them since I don't use them much.
Disclaimer: I can't promise the following is a good way to go about it, but working through it sounds fun. Let's take it for a spin, shall we?.
A few obligatory imports
First, let's toss some data types out there. I'm going to fill in some details and tweak things a bit, in order to define a simple "file system" that we can actually interact with.
type Path = String
type Response = Maybe String
type Contents = [String]
data Operation = Cd Path
| Ls
| MkDir Path
| Quit
deriving (Read, Show)
Next, we'll do something a bit edgy... strip out all the monads. What? This is madness! Perhaps, but sometimes all the hidden plumbing that >>= provides hides things just a bit too much.
For the file system itself, we'll just store the current working directory and a map from paths to their children. We'll also need a handful of functions to interact with it.
data Filesystem = Filesystem { wd :: Path, files :: M.Map Path Contents }
deriving Show
newFS = Filesystem "/" (M.singleton "/" [])
isDirectory p fs = M.member p $ files fs
children p fs = fromMaybe [] . M.lookup p $ files fs
cd p fs = fs { wd = p }
create p fs = let newPath = wd fs ++ p ++ "/"
addPath = M.insert newPath [] . M.adjust (p:) (wd fs)
in (newPath, fs { files = addPath $ files fs })
Now for a monad-less version of the step function. It needs to take an Operation and a Filesystem, and return a Response and a (possibly modified) Filesystem:
step :: Operation -> Filesystem -> (Response, Filesystem)
step (Cd d) fs = (Just "Ok\n", cd d fs)
step (MkDir d) fs = first (\d -> Just $ "Created " ++ d ++ "\n") $ create d fs
step Ls fs = let files = children (wd fs) fs
in (Just $ unlines files, fs)
step Quit fs = (Nothing, fs)
...hmm, that type signature already looks a lot like the guts of a State monad. Oh well, just ignore it for now, and charge blindly onward.
Now, what we want is a function that will provide a general-purpose interface to a Filesystem interpreter. Particularly, we want the interface to be at least somewhat self-contained so that whatever uses the interface doesn't have to step through manually, yet we want the interface to be sufficiently oblivious to the code using it that we can wire it up to the IO monad, some other Monad, or even no monad at all.
What this tells us primarily is that we'll need to interleave the external code with the interpreter in some fashion, rather than having either part be in control. Now, Haskell is a functional language, so that means that using lots of higher-order functions is good, right? Sounds plausible to me, so here's the strategy we'll use: If a function doesn't know what to do next, we'll hand it another function that we assume does. Repeat until everybody knows what's going on. A flawless plan, no?
The heart of it all is the step function, so we'll start by just calling that.
interp1 :: Operation -> Filesystem -> (Response, Filesystem)
interp1 op fs = step op fs
...well, it's a start. I guess. But wait, where is the Operation coming from? We need the external code to provide that, but we can't just ask for it without getting all mixed up with unsavory characters like IO. So we get another function to do the dirty work for us:
interp2 :: ((Operation -> (Response, Filesystem)) -> t) -> Filesystem -> t
interp2 inp fs = inp (\op -> step op fs)
Of course, now all we have is some stupid t that we don't even know what it is. We know it has to have a Response and a Filesystem in it somewhere, but we can't do anything with it, so we'll hand it back to another function, along with some instructions on how to proceed... which will of course involve passing in yet more functions. It's functions all the way down, you know.
interp3 :: ((Operation -> (Response, Filesystem)) -> a)
-> (a -> ((Response, Filesystem) -> b) -> c)
-> (Filesystem -> b)
-> (String -> Filesystem -> b)
-> Filesystem
-> c
interp3 inp check done out fs = check (inp (\op -> step op fs)) test
where test (Nothing, fs) = done fs
test (Just s, fs) = out s fs
...well that's pretty ugly. But don't worry, all is going according to plan. We can make a couple observations next:
The type a only exists between inp and check, so in hindsight, we might as well combine them ahead of time and just pass the composed function to the interpreter.
When we call done, it ought to mean exactly what it says on the tin. So the return type for done should be the same as the whole interpreter, meaning b and c ought to be the same type.
Now, if done ends the whole thing, what's out? As the name none-too-subtly implies, it's providing output to the external code, but where does it go after that? It needs to loop back into the interpreter somehow, and we might note that our interpreter is not yet recursive. The way forward is clear--the interpreter, like Jormungand, thus seizes its own tail; looping back around indefinitely till the interpretation finishes (or until Ragnarök, whichever comes first).
interp4 :: ((Operation -> (Response, Filesystem))
-> ((Response, Filesystem) -> r) -> r)
-> (Filesystem -> r)
-> (String -> Filesystem -> (Filesystem -> r) -> r)
-> Filesystem
-> r
interp4 checkInp done out fs = checkInp (\op -> step op fs) test
where loop = interp4 checkInp done out
test (Nothing, fs) = done fs
test (Just s, fs) = out s fs loop
...oh, did I mention that it works now? No, seriously!
Here's some IO code to use the interface:
ioIn f k = putStr "> " >> (k . f =<< readLn)
ioDone fs = putStrLn "Done" >> return fs
ioOut x fs k = putStr x >> k fs
ioInterp :: IO Filesystem
ioInterp = interp4 ioIn ioDone ioOut newFS
And here's code that runs a list of commands, producing a list of output strings:
scriptIn f k (x:xs) = k (f x) xs
scriptDone fs xs = ["Done\n"]
scriptOut r fs k xs = r : k fs xs
scriptInterp :: [Operation] -> [String]
scriptInterp = interp4 scriptIn scriptDone scriptOut newFS
Examples of running both in GHCi here, if just the code doesn't tickle your imagination sufficiently.
Well, that's that. Or is it? Frankly, that interpreter is code only a mother could love. Is there something that would tie it all together elegantly? Something to reveal the underlying structure of the code?
...okay, so it's pretty obvious where this leads. The overall design of functions tail-calling each other in circles looks an awful lot like continuation-passing style, and not once but twice in the interpreter's type signature can be found the characteristic pattern (foo -> r) -> r, better known as the continuation monad.
Unfortunately, even after all that, continuations make my head hurt and I'm not sure how best to disentangle the very ad-hoc structure of the interpreter into a computation running in a MonadCont.
I can think of two solutions here:
1) Use a monad transformer library. I can't improve on Shimuuar's reply, except in some details on the libraries. Transformers by itself doesn't provide the necessary instances; you would need to use transformers and either monads-tf or monads-fd, which offer implementations based on type families and fundeps, respectively. I prefer monads-tf if you go this route. The api is almost identical to that of mtl. I don't have experience with MonadLib, but it looks quite good also.
2) Write your main loop in IO, and for each loop iteration call runState to evaluate the state monad. Something like the following:
loop path state = do
op <- readOp
let ((newpath, resp), newstate) = runState (step path op) state
print resp
loop newpath newstate
This should work, but it's far less idiomatic than using monad transformers.
Require your instances of FS to be instance of MonadIO, not just Monad:
class MonadIO m => FS m where ...
Then you will have available the liftIO method to lift FS into IO:
liftIO :: MonadIO m => m a -> IO a
so you can write in the IO monad:
files <- liftIO $ children currentDir
etc. Of course, that means you will need to implement liftIO
for each FS before you even write the FS instance, but for
this application (without having seen the actual details)
it sounds like that should be simple.

Resources