h$s<oE      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~(c) Andrey Mulik 2020 BSD-stylework.a.mulik@gmail.comnon-portable (GHC extensions) Safe-Inferred&'*sdp-io+Windows: > "" :\ "file" <- "file" > "c:" :\ "file" <- "c:file" > "c:\" :\ "file" <- "c:\file" > "\\shared\" :\ "test" <- "\\shared\test" > "\\shared" :\ "" <- "\\shared" > "\\?\UNC\shared\" :\ "file" <- "\\?\UNC\shared\file" > "\\?\" :\ UNCshared\\file <- "\\?\UNCshared\file" > "\\?\d:\" :\ "file" <- "\\?\d:\file" > "" :\ "d" <- "d" Posix: > "" :\ "test" <- " test" > "/" :\ "test" <- "/test" > "" :\ "testfile" <- "test file" > "" :\ "file" <- "file"+sdp-io)Splits/joins directories and a file name.,sdp-ioSeparates filepath into a search path - list of ancestors without trailing separators and file name (if any):Posix: > Dirs [" ", "home", "user", ".ghci"] <- "homeuser.ghci" > Dirs ["", "home", "user"] <- "homeuser " > Dirs ["", "home", "user"] <- " home/user"Windows: > Dirs ["C:\", "home", "user"] <- "C:\home\user\" > Dirs ["C:\","home","user"] <- "C:\home\user",? concatenates the file path regardless of a trailing separator.-sdp-ioSeparates filepath into a search path - list of ancestors with trailing separators and file name (if any):Posix: > Path ["", "home", "user", ".ghci"] <- "homeuser.ghci" > Path ["", "home", "user"] <- "homeuser " > Path ["", "home", "user"] <- "homeuser"Windows: > Path ["C:\", "home\", "user\"] <- "C:\home\user\" > Path ["C:\", "home\", "user"] <- "C:\home\user"-? concatenates the file path regardless of a trailing separator..sdp-ioSplit a filename into directory and file. The first component will often end with a trailing slash. "/directory/" :/ "file.ext" <- "/directory/file.ext" "file/" :/ "bob.txt" <- "file/bob.txt" "./" :/ "bob" <- "bob" Posix: > "" : "" <- "/"Windows: > "c:" :/ "" <- "c:"(Combine two paths with a path separator.If the second path looks like an absolute path or a drive, then it returns the second. )"directory" :/ "/file.ext" == "/file.ext" Posix: > " directory" : "file.ext" == " directoryfile.ext" > "" : "tmp" == "/tmp" > "x:" : "foo" == "x:foo" > "home" : "user" == "/user" > "home" : "user" == "homeuser"Windows: > " directory" : "file.ext" == "/directory\file.ext" > "C:\foo" :/ "bar" == "C:\foo\bar" > "home" :/ "C:\bob" == "C:\bob" > "home" :/ "bob" == "home\bob" "C:\\home" :/ "\\bob" == "\\bob" "home" :/ "\\bob" == "\\bob" "home" :/ "/bob" == "/bob" ?"D:\\foo" :/ "C:bar" == "C:bar" "C:\\foo" :/ "C:bar" == "C:bar"/sdp-ioAdd an extensions. x :.. [] = x -- forall x path :.. [ext] = path :. ext -- forall path ext "dir/file" :.. ["fb2", "zip"] == "dir/file.fb2.zip" "dir/file" :.. ["fb2", ".zip"] == "dir/file.fb2.zip" "pacman" :.. ["pkg", "tar", "xz"] == "pacman.pkg.tar.xz"8Split on the extensions. Note that points are discarded. ("file" :.. []) <- "file" ("out" :.. ["txt"]) <- "out.txt" ("/etc/pam.d/" :.. []) <- "/etc/pam.d/" ("dir.d/fnya" :.. []) <- "dir.d/fnya" ("dir.d/data" :.. ["bak"]) <- "dir.d/data.bak" ("/directory/path" :.. ["ext"]) <- "/directory/path.ext" ("file/path." :.. ["txt", "alice", "bob"]) <- "file/path.txt.alice.bob"This function separates the extensions and also considers the case when the file name begins with a period. splitExtensions "file/.path.txt.alice.bob" == ("file/", ".path.txt.alice.bob") ("file/.path" :.. [txt, alice, bob]) <- "file/.path.txt.alice.bob" splitExtensions ".bashrc" == ("", ".bashrc") (".bashrc" :.. []) <- ".bashrc"0sdp-ioAdd an extension. "/directory/path" :. "ext" == "/directory/path.ext" "file.txt" :. "tar" == "file.txt.tar" "file." :. ".tar" == "file..tar" "file" :. ".xml" == "file.xml" "/" :. "d" == "/.d"2Windows: > "\\share" :. ".txt" == "\\share\.txt"7Split on the extension. Note that points are discarded. ("file" :. "") <- "file" ("out" :. "txt") <- "out.txt" ("/etc/pam.d/" :. "") <- "/etc/pam.d/" ("dir.d/fnya" :. "") <- "dir.d/fnya" ("dir.d/data" :. "bak") <- "dir.d/data.bak" ("/directory/path" :. "ext") <- "/directory/path.ext" ("file/path.txt.alice" :. "bob") <- "file/path.txt.alice.bob"$Note that filenames starting with a . are handled correctly: (".bashrc" :. "") <- ".bashrc"1sdp-ioDefault path separator.2sdp-ioSeparator check.3sdp-ioGet a list of $s in the $PATH.4sdp-ioIs a $ valid? This function checks for invalid names, invalid characters, but doesn't check if length limits are exceeded, as these are typically filesystem dependent. )isValid "" == False isValid "\0" == FalsePosix: > isValid "/random_ path:*" == True > isValid x => not (null x)Windows: > isValid "c:\test" == True > isValid "c:\test:of_test" == False > isValid "test*" == False > isValid "c:\test\nul" == False > isValid "c:\test\prn.txt" == False > isValid "c:\nul\file" == False > isValid "\\" == False > isValid "\\\foo" == False > isValid "\\?\D:file" == False > isValid "footbar" == False > isValid "nul .txt" == False > isValid " nul.txt" == True5sdp-ioTake a FilePath and make it vali, doesn't change already valid FilePaths: isValid (makeValid x) == True isValid x => makeValid x == x makeValid "" == "_" makeValid "file\0name" == "file_name"#Windows: > makeValid "c:\already\valid" == "c:\already\valid" > makeValid "c:\test:of_test" == "c:\test_of_test" > makeValid "test*" == "test_" > makeValid "c:\test\nul" == "c:\test\nul_" > makeValid "c:\test\prn.txt" == "c:\test\prn_.txt" > makeValid "c:\testprn.txt" == "c:\testprn_.txt" > makeValid "c:\nul\file" == "c:\nul_\file" > makeValid "\\\foo" == "\\drive" > makeValid "\\?\D:file" == "\\?\D:\file" > makeValid "nul .txt" == "nul _.txt"6sdp-io/Is a path relative, or is it fixed to the root?Posix: > isRelative "test/path" == True > isRelative "/test" == False > isRelative "/" == FalseWindows: isRelative "path\\test" == True isRelative "c:\\test" == False isRelative "c:test" == True isRelative "c:\\" == False isRelative "c:/" == False isRelative "c:" == True isRelative "\\\\foo" == False isRelative "\\\\?\\foo" == False isRelative "\\\\?\\UNC\\foo" == False isRelative "/foo" == True isRelative "\\foo" == True/"A UNC name of any format [is never relative]."5"You can't use the "\?" prefix with a relative path."7sdp-ioSame as not . 6.8sdp-ioNormalise a file name: * // outside of the drive can be made blank * / -> 1 * ./ -> "" normalise "." == "."Posix: > normalise "file\test///" == "file\test" > normalise "file. test" == "file/test" > normalise "testfile..bobfred" == "testfile..bobfred" > normalise "..bobfred" == "..bobfred" > normalise ".bobfred " == "bobfred/" normalise "./" == "./" normalise "./." == "./" normalise "/./" == "/" normalise "/" == "/" normalise "bob/fred/." == "bob/fred/" normalise "//home" == "/home"Windows: > normalise "c:\file/bob\" == "C:\file\bob\" > normalise "c:\" == "C:\" > normalise "C:.\" == "C:" > normalise "\\server\test" == "\\server\test" > normalise "/servertest" == "\\server\test" > normalise "c:/file" == "C:\file" > normalise "/file" == "\file" > normalise "\" == "\" > normalise "." == "\"9sdp-ioEquality of two $s. If you call !System.Directory.canonicalizePath first this has a much better chance of working. Note that this doesn't follow symlinks or DOSNAMEs. x == y ==> equalFilePath x y normalise x == normalise y ==> equalFilePath x y ;equalFilePath "foo" "foo/" not (equalFilePath "foo" "/foo")$Posix: > not (equalFilePath "foo" FOO)!Windows: > equalFilePath "foo" FOO# > not (equalFilePath "C:" "C:/"):sdp-ioContract a filename, based on a relative path. Note that the resulting path will never introduce ..* paths, as the presence of symlinks means ../b may not reach a/b if it starts from a/c. For a worked example see  http://neilmitchell.blogspot.co.uk/2015/10/filepaths-are-subtle-symlinks-are-hard.htmlthis blog post.The corresponding  makeAbsolute function can be found in System.Directory. makeRelative "/directory" "/directory/file.ext" == "file.ext" Valid x => makeRelative (takeDirectory x) x `equalFilePath` takeFileName x makeRelative x x == "." Valid x y => equalFilePath x y || (isRelative x && makeRelative y x == x) || equalFilePath (y makeRelative y x) xPosix: > makeRelative "Home" "home bob" == "home/bob" > makeRelative "home" "homebobfoo bar" == "bobfoo?bar" > makeRelative "/fred" "bob" == "bob" > makeRelative "filetest" "file'test/fred" == "fred" > makeRelative "filetest" "filetestfred#" == "fred/" > makeRelative "some path" "somepathabc" == "ab/c"Windows: > makeRelative "C:\Home" "c:\home\bob" == "bob" > makeRelative "C:\Home" "c:homebob" == "bob" > makeRelative "C:\Home" "D:\Home\Bob" == "D:\Home\Bob" > makeRelative "C:\Home" "C:Home\Bob" == "C:Home\Bob" > makeRelative "Home" "%home/bob" == "bob" > makeRelative "" "" == "/"$*+,-./0123456789:$2467589:31*0/.+-,+5.5/707(c) Andrey Mulik 2020 BSD-stylework.a.mulik@gmail.comportable Safe-Inferred`A/;sdp-io Computation ; hdl makes handle hdl/ closed. Before the computation finishes, if hdl* is writable its buffer is flushed as for A. Performing ; on a handle that has already been closed has no effect; doing so is not an error. All other operations on a closed handle will fail. If ;: fails for any reason, any further operations (apart from ;() on the handle will still fail as if hdl had been successfully closed.<sdp-io For a handle hdl$ which attached to a physical file, > hdl0 returns the size of that file in 8-bit bytes.=sdp-io= hdl size) truncates the physical file with handle hdl to size bytes.>sdp-io File size .?sdp-io Computation ? is equal to @ @sdp-ioFor a readable handle hdl, @ hdl returns ) if no further input can be taken from hdl or for a physical file, if the current I/O position is equal to the length of the file. Otherwise, it returns .NOTE: @ may block, because it has to attempt to read from the stream to determine whether there is any more data to be read.Asdp-io The action A hdl0 causes any items buffered for output in handle hdl2 to be sent immediately to the operating system.This operation may fail with: if the device is full; if a system resource limit would be exceeded. It is unspecified whether the characters in the buffer are discarded or retained under these circumstances.Bsdp-ioB hdl mode' sets the mode of buffering for handle hdl" on subsequent reads and writes.#If the buffer mode is changed from  or  to , thenif hdl+ is writable, the buffer is flushed as for A;if hdl: is not writable, the contents of the buffer is discarded.This operation may fail with: if the handle has already been used for reading or writing and the implementation does not allow the buffering mode to be changed.Csdp-ioC hdl( returns the current buffering mode for hdl.Dsdp-io buffering .Esdp-ioE hdl% returns the current I/O position of hdl# as a value of the abstract type  HandlePosn.Fsdp-io If a call to E hdl returns a position p, then F p sets the position of hdl6 to the position it held at the time of the call to E.This operation may fail with:0 if a system resource limit would be exceeded.Gsdp-ioG hdl mode i sets the position of handle hdl depending on mode. The offset i" is given in terms of 8-bit bytes.If hdl is block- or line-buffered, then seeking to a position which isn't in the current buffer will first cause any items in the output buffer to be written to the device, and then cause the input buffer to be discarded. Some handles may not be seekable (see M), or only support a subset of the possible positioning operations (for instance, it may only be possible to seek to the end of a tape, or to a positive offset from the beginning or current position). It isn't possible to set a negative I/O position, or for a physical file, an I/O position beyond the current end-of-file.This operation may fail with: if the > isn't seekable, or doesn't support the requested seek mode.0 if a system resource limit would be exceeded.Hsdp-ioH hdl, returns the current position of the handle hdl, as the number of bytes from the beginning of the file. The value returned may be subsequently passed to G4 to reposition the handle to the current position.This operation may fail with: if the Handle isn't seekable.Isdp-ioSame as .Jsdp-ioSame as .Ksdp-ioSame as .Lsdp-ioSame as .Msdp-ioSame as .Nsdp-io&Is the handle connected to a terminal?Osdp-io;Set the echoing status of a handle connected to a terminal.Psdp-io;Get the echoing status of a handle connected to a terminal.Qsdp-ioEcho .Rsdp-ioR hdl t* waits until input is available on handle hdl. It returns " as soon as input is available on hdl, or # if no input is available within t milliseconds. Note that  hWaitForInput waits until one or more full characters are available, which means that it needs to do decoding, and hence may fail with a decoding error.If t is less than zero, then R waits indefinitely.This operation may fail with:% if the end of file has been reached.a decoding error, if the input begins with an invalid byte sequence in this Handle's encoding.9NOTE for GHC users: unless you use the -threaded flag, R hdl t where t >= 0 will block all other Haskell threads for the duration of the call. It behaves like a safe foreign call in this respect.Ssdp-ioS hdl indicates whether at least one item is available for input from handle hdl.This operation may fail with:% if the end of file has been reached.Tsdp-io Computation U hdl9 reads a character from the file or channel managed by hdl*, blocking until a character is available.This operation may fail with:% if the end of file has been reached.Usdp-ioU hdl7 reads a character from the file or channel managed by hdl,, blocking until a character is available.This operation may fail with:% if the end of file has been reached.Vsdp-io Computation V hdl ch writes the character ch% to the file or channel managed by hdl;. Characters may be buffered if buffering is enabled for hdl.This operation may fail with:5 if another system resource limit would be exceeded if the device is fullWsdp-io1Read a character from the standard input device, U .Xsdp-io0Write a character to the standard output device V .Ysdp-ioSelect binary mode () or text mode () on a open handle.$This has the same effect as calling c with , together with a with .Zsdp-ioZ name mode act opens a file using [6 and passes the resulting handle to the computation act+. The handle will be closed on exit from Z=, whether by normal termination or by raising an exception.[sdp-ioLike , but open the file in binary mode. On Windows, reading a file in text mode (which is the default) will translate CRLF to LF, and writing will translate LF to CRLF. This is usually what you want with text files. With binary files this is undesirable; also, as usual under MS OSes, text mode treats control-Z as EOF. Binary mode turns off all special treatment of end-of-line and end-of-file characters.\sdp-io\ hdl buf count reads data from the handle hdl into the buffer buf until either EOF is reached or count 8-bit bytes have been read. It returns the number of bytes actually read. This may be zero if EOF was reached before any data was read (or if count is zero).\ never raises an EOF exception, instead it returns a value smaller than count.If the handle is a pipe or socket, and the writing end is closed, \% will behave as if EOF was reached.\ ignores the prevailing # and  on the , and reads bytes directly.]sdp-io] hdl buf count reads data from the handle hdl into the buffer buf/. If there is any data available to read, then ] returns it immediately; it only blocks if there is no data to be read.It returns the number of bytes actually read. This may be zero if EOF was reached before any data was read (or if count is zero).] never raises an EOF exception, instead it returns a value smaller than count.If the handle is a pipe or socket, and the writing end is closed, ]# will behave as if EOF was reached.] ignores the prevailing # and  on the , and reads bytes directly.^sdp-io^ hdl buf count* writes count 8-bit bytes from the buffer buf to the handle hdl.^/ ignores any text encoding that applies to the , writing the bytes directly to the underlying file or device.This operation may fail with:   if the handle is a pipe or socket, and the reading end is closed. (If this is a POSIX system, and the program has not asked to ignore SIGPIPE, then a SIGPIPE may be delivered instead, whose default action is to terminate the program)._sdp-io` hdl buf count reads data from the handle hdl into the buffer buf until either EOF is reached, or count 8-bit bytes have been read, or there is no more data available to read immediately.` is identical to \, except that it will never block waiting for data to become available, instead it returns only whatever data is available. To wait for data to arrive before calling `, use R.If the handle is a pipe or socket, and the writing end is closed, `# will behave as if EOF was reached.` ignores the prevailing # and  on the , and reads bytes directly.NOTE: on Windows, this function doesn't work correctly; it behaves identically to \.`sdp-io` hdl buf count reads data from the handle hdl into the buffer buf until either EOF is reached, or count 8-bit bytes have been read, or there is no more data available to read immediately.` is identical to \, except that it will never block waiting for data to become available, instead it returns only whatever data is available. To wait for data to arrive before calling `, use R.If the handle is a pipe or socket, and the writing end is closed, `# will behave as if EOF was reached.` ignores the prevailing # and  on the , and reads bytes directly.NOTE: on Windows, this function doesn't work correctly; it behaves identically to \.asdp-ioSet the ? on the specified Handle. All buffered data is flushed first.bsdp-io1Look up the named Unicode encoding. May fail with.isDoesNotExistError if the encoding is unknownThe set of known encodings is system-dependent, but includes at least:UTF-8UTF-16, UTF-16BE, UTF-16LEUTF-32, UTF-32BE, UTF-32LEThere is additional notation (borrowed from GNU iconv) for specifying how illegal characters are handled: a suffix of /IGNORE, e.g. UTF-8/IGNORE, will cause all illegal sequences on input to be ignored, and on output will drop all code points that have no representation in the target encoding.a suffix of //TRANSLIT will choose a replacement character for illegal sequences or code points.a suffix of //ROUNDTRIP will use a PEP383-style escape mechanism to represent any invalid bytes in the input as Unicode codepoints (specifically, as lone surrogates, which are normally invalid in UTF-32). Upon output, these special codepoints are detected and turned back into the corresponding original byte.In theory, this mechanism allows arbitrary data to be roundtripped via a String with no loss of data. In practice, there are two limitations to be aware of:This only stands a chance of working for an encoding which is an ASCII superset, as for security reasons we refuse to escape any bytes smaller than 128. Many encodings of interest are ASCII supersets (in particular, you can assume that the locale encoding is an ASCII superset) but many (such as UTF-16) are not.If the underlying encoding is not itself roundtrippable, this mechanism can fail. Roundtrippable encodings are those which have an injective mapping into Unicode. Almost all encodings meet this criteria, but some do not. Notably, Shift-JIS (CP932) and Big5 contain several different encodings of the same Unicode codepoint.On Windows, you can access supported code pages with the prefix CP; for example, CP1250.csdp-ioc hdl3 encoding changes the text encoding for the handle hdl, to encoding. The default encoding when a  is created is 5, namely the default encoding for the current locale. To create a  with no encoding at all, use [8. To stop further encoding or decoding on an existing , use Y.c may need to flush buffered data in order to change the encodingdsdp-ioReturn the current # for the specified , or  if the  is in binary mode.Note that the # remembers nothing about the state of the encoder/decoder in use on this +. For example, if the encoding in use is UTF-16 , then using d and c to save and restore the encoding may result in an extra byte-order-mark being written to the file.esdp-io Encoding , 7set hdl [encoding := Nothing] = hSetBinaryMode hdl Truefsdp-io)The function creates a temporary file in %. The created file isn't deleted automatically, so you need to delete it manually.The file is created with permissions such that only the current user can read/write it.With some exceptions (see below), the file will be created securely in the sense that an attacker should not be able to cause f to overwrite another file on the filesystem using your credentials, by putting symbolic links (on Unix) in the place where the temporary file is to be created. On Unix the O_CREAT and O_EXCL flags are used to prevent this attack, but note that O_EXCL is sometimes not supported on NFS filesystems, so if you rely on this behaviour it is best to use local filesystems only.gsdp-ioLike f$, but opens the file in binary mode.hsdp-ioLike f(, but uses the default file permissions.isdp-ioLike g(, but uses the default file permissions. "! #)('&%;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghi;)('&%<=>?@ABCDEF"! GHIJKLMNOPQRSTUVWXYZ[\]^_`fghicde#b a(c) Andrey Mulik 2020 BSD-stylework.a.mulik@gmail.comportable Safe-Inferred>n`jsdp-ioj. is a type class of text file representations.ksdp-ioRead one text line from handle.lsdp-ioPut text to handle.msdp-ioPut text line to handle.nsdp-ion8 is a type class that represents the contents of a file.n provides only basic read and write operations. It doesn't allow, for example, changing the ) or handle the concatenation of the file contents with the appendable information.osdp-iohGetContents hdl reads the contents of the file. Reading may be both lazily (in this case hdl should be semi-closed until the file end is reached) or strictly. After reading the file, hdl should be closed.Once a semi-closed handle becomes closed, the contents becomes fixed. The contents of this final value is only partially specified: it will contain at least all the items of the stream that were evaluated prior to the handle becoming closed.This operation may fail with:/isEOFError if the end of file has been reached.psdp-iohPutContents hdl file writes the file contents to hdl.This operation may fail with: if the device is full; or4 if another system resource limit would be exceeded.If p changes the recording mode (buffering, binary/text), it should return the original Handle settings.qsdp-ioq? is type class of file path (data destination) representations.rsdp-iohOpen path mode; open new text handle with block buffering and given mode using path identifier.This operation may fail with:isAlreadyInUseError3 if the file is already open and cannot be reopenedisDoesNotExistError if the file does not existisPermissionError5 if the user doesn't have permission to open the filessdp-iohOpenWith path mode buf bin% open new handle with buffering mode buf, binary mode bin and ) mode using path identifier.This operation may fail with:3 if the file is already open and cannot be reopened if the file does not exist5 if the user doesn't have permission to open the filetsdp-ioOpen new temp file  by given source identifier.usdp-ioJust o .vsdp-ioJust p .wsdp-iowithFile path mode act opens a file using r6 and passes the resulting handle to the computation act+. The handle will be closed on exit from withFile;, whether by normal termination or by raising an exception.If closing the handle raises an exception, then this exception will be raised by withFile rather than any exception raised by act.xsdp-ioThe x0 function reads a file and returns its contents.The specifics of reading a file (laziness/strictness, possible exceptions) depend on the type of resource and the o implementation.ysdp-iowriteFile path file function writes the file value, to the path.zsdp-ioappendFile path file appends the file value, to the path.{sdp-ioSame as hGetLine stdin.|sdp-ioSame as hPutStr stdout.}sdp-ioSame as hPutStrLn stdout.~sdp-ioShort version of {.sdp-ioShort version of }. "! #)%&(';<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~qrstnopuvwxyzjklm{|}~                ! " # $ % & ' ( ) * + , - . . /0 /1 /2 /3 45 67 89 8: 8; 8< 8=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ] ^ _ ` a                                                !sdp-io-0.2-Aurc2tZC8tiKhY1ms0QFacSystem.IO.Handle Data.FilePathSystem.IO.ClassesSystem.IO.Error isFullErrorisPermissionErrorisIllegalOperationError isEOFErrorGHC.IO.ExceptionResourceVanishedbase System.IOlocaleEncoding GHC.IO.Handle HandlePosnGHC.IO.Handle.FDstderrstdinGHC.IO.Encodingchar8utf32beutf32leutf32utf16beutf16leutf16utf8_bomutf8latin1stdoutGHC.IO.Handle.TypesnoNewlineTranslationnativeNewlineModeuniversalNewlineMode nativeNewlineHandleBlockBuffering LineBuffering NoBuffering BufferModeCRLFLFNewlineoutputNLinputNL NewlineMode GHC.IO.Device SeekFromEnd RelativeSeek AbsoluteSeekSeekModeGHC.IO.Encoding.Types TextEncodingGHC.IOFilePath GHC.IO.IOMode ReadWriteMode AppendMode WriteModeReadModeIOMode:\\://DirsPath:/:..:.PathSep isPathSepgetPathisValid makeValid isRelative isAbsolute normalise equalFilePath makeRelativehClose hGetFileSize hSetFileSizefileSizeisEOFhIsEOFhFlush hSetBuffering hGetBuffering hBufferinghGetPosnhSetPosnhSeekhTellhIsOpen hIsClosed hIsReadable hIsWritable hIsSeekablehIsTerminalDevicehSetEchohGetEchoecho hWaitForInputhReady hLookAheadhGetCharhPutChargetCharputCharhSetBinaryModewithBinaryFileopenBinaryFilehGetBuf hGetBufSomehPutBufhPutBufNonBlockinghGetBufNonBlockinghSetNewlineModemkTextEncoding hSetEncoding hGetEncodingencoding openTempFileopenBinaryTempFileopenTempFileWith'openBinaryTempFile' IsTextFilehGetLinehPutStr hPutStrLnIsFile hGetContents hPutContents IsFilePathhOpen hOpenWith hOpenTemp getContents putContentswithFilereadFile writeFile appendFilegetLineputStrputStrLngetsputs$fIsFilePath[] $fIsFile[]$fIsTextFile[]fmr-0.1-LNq7gyGWDtn37lWdPWoHni Data.FieldFieldghc-prim GHC.TypesTrueFalseopenFile GHC.MaybeNothingisAlreadyInUseErrorisDoesNotExistError catchIOErrorannotateIOError modifyIOErrorioeSetFileName ioeSetHandleioeSetLocationioeSetErrorStringioeSetErrorTypeioeGetFileName ioeGetHandleioeGetLocationioeGetErrorStringioeGetErrorTypeisResourceVanishedErrorTypeisUserErrorTypeisPermissionErrorTypeisIllegalOperationErrorTypeisEOFErrorTypeisFullErrorTypeisAlreadyInUseErrorTypeisDoesNotExistErrorTypeisAlreadyExistsErrorTyperesourceVanishedErrorType userErrorTypepermissionErrorTypeillegalOperationErrorType eofErrorType fullErrorTypealreadyInUseErrorTypedoesNotExistErrorTypealreadyExistsErrorTypeisResourceVanishedError isUserErrorisIllegalOperationisAlreadyExistsError mkIOError tryIOErrorioError IOErrorType userErrorIOError