NovelIO


Working with Files

Working with Files in NovelIO is a little different from standard .NET IO. Perhaps the most significant change is the handling of file paths.

Standard .NET IO uses string to represent file paths. NovelIO instead uses the 'Filename' type, this is effectively a string wrapper that cannot contain invalid file name characters.

Creating Filepaths

The first method of creating Filepaths is to use active patterns on a string, for example:

match "test.txt" with
|ValidFilePath fName -> Some fName // do something with the valid filename
|InvalidFilePath -> None // handle the invalid filename case

If we know that a conversion to a Filepath is definitely going to be succesful, we can instead use File.assumeValidFilename

let fName = File.Path.fromValid "test.txt"

Should we be mistaken about the supplied string being a valid filename, an ArgumentException will be thrown.

Using File functions

The File modules contains functions very similar to System.IO.File defined in standard .NET, these functions are presented using curried arguments and their returns are wrapped by the IO<'a> type.

io {
   let! lines = File.readAllLines fName
   return lines
}

File Channels

If you need more fine-grained control over File IO, the way to achieve this is using Channels. Text and Binary Channels (TChannels and BChannels) support explicit reading and writing of their corresponding datatype.

let readFileUntilEnd path =
    File.withTextChannel File.Open.defaultRead path (fun channel ->
        IO.Loops.untilM (TextChannel.isEOF channel) (TextChannel.getLine channel))

It is recommended that you use that the withChannel functions provided so that the channel will be automatically cleaned up after its use rather than explicitly opening and closing channels manually.

You can find more about channels on the channels page.

namespace NovelFS
namespace NovelFS.NovelIO
active recognizer ValidFilePath: string -> Choice<FilePath,unit>

Full name: NovelFS.NovelIO.PathDiscriminators.( |ValidFilePath|InvalidFilePath| )
val fName : FilePath
union case Option.Some: Value: 'T -> Option<'T>
active recognizer InvalidFilePath: string -> Choice<FilePath,unit>

Full name: NovelFS.NovelIO.PathDiscriminators.( |ValidFilePath|InvalidFilePath| )
union case Option.None: Option<'T>
val fName : FilePath

Full name: Files.fName
module File

from NovelFS.NovelIO
module Path

from NovelFS.NovelIO.File
val fromValid : path:string -> FilePath

Full name: NovelFS.NovelIO.File.Path.fromValid
val io : IO.IOBuilder

Full name: NovelFS.NovelIO.IOBuilders.io
val lines : string list
val readAllLines : filename:FilePath -> IO<string list>

Full name: NovelFS.NovelIO.File.readAllLines
val readFileUntilEnd : path:FilePath -> IO<string list>

Full name: Files.readFileUntilEnd
val path : FilePath
val withTextChannel : options:FileOpenOptions -> fName:FilePath -> fChannel:(TChannel -> IO<'a>) -> IO<'a>

Full name: NovelFS.NovelIO.File.withTextChannel
module Open

from NovelFS.NovelIO.File
val defaultRead : FileOpenOptions

Full name: NovelFS.NovelIO.File.Open.defaultRead
val channel : TChannel
Multiple items
module IO

from NovelFS.NovelIO

--------------------
type IO<'a> =
  private | Return of 'a
          | SyncIO of (unit -> IO<'a>)
          | AsyncIO of Async<IO<'a>>

Full name: NovelFS.NovelIO.IO<_>
module Loops

from NovelFS.NovelIO.IO
val untilM : pAct:IO<bool> -> f:IO<'a> -> IO<'a list>

Full name: NovelFS.NovelIO.IO.Loops.untilM
module TextChannel

from NovelFS.NovelIO
val isEOF : channel:TChannel -> IO<bool>

Full name: NovelFS.NovelIO.TextChannel.isEOF
val getLine : channel:TChannel -> IO<string>

Full name: NovelFS.NovelIO.TextChannel.getLine
Fork me on GitHub