Line Filters in F#

A line filter is a common type of program that reads input on stdin, processes it, and then prints some derived result to stdout. grep and sed are common line filters.

Here’s an example line filter in F# that writes a capitalized version of all input text. You can use this pattern to write your own F# line filters.

open System
open System.IO

[<EntryPoint>]
let main argv =
    // Read input from stdin line by line
    use reader = new StreamReader(Console.OpenStandardInput())
    
    // Process each line
    while not reader.EndOfStream do
        let line = reader.ReadLine()
        let uppercaseLine = line.ToUpper()
        
        // Write out the uppercased line
        printfn "%s" uppercaseLine
    
    // Check for errors during reading
    match reader.BaseStream with
    | :? FileStream as fs when fs.Length = 0L ->
        eprintfn "error: No input provided"
        1  // Exit with error code
    | _ -> 0  // Exit successfully

In this F# version:

  1. We use System.IO.StreamReader to read from standard input, which gives us a convenient way to read input line by line.

  2. We use a while loop to continue reading lines until we reach the end of the stream.

  3. For each line, we use the ToUpper() method to convert it to uppercase.

  4. We use printfn to write the uppercased line to standard output.

  5. After the loop, we check if there was any input at all. If not, we print an error message to standard error using eprintfn.

  6. The main function returns an integer, which serves as the exit code of the program (0 for success, non-zero for error).

To try out our line filter, first make a file with a few lowercase lines.

$ echo 'hello'   > /tmp/lines
$ echo 'filter' >> /tmp/lines

Then use the line filter to get uppercase lines.

$ cat /tmp/lines | dotnet run
HELLO
FILTER

Note that to run this F# program, you need to have the .NET SDK installed and compile the program first. You would typically save this code in a file with a .fs extension, create a project file, and then use dotnet run to compile and run the program.