Search code examples
f#stdinconsole.readline

What's the best way to read from stdin?


I am currently trying to learn F# better and I am using codingame as an source of programming quizzes.

Most of the quizess involves reading some values from stdin, like the first ten values on stdin will be ints, the next five will be strings.

Currently, I am using this function to read the data, but it feels very "un-f#".

let N = 5
let Reader i =
    Console.In.ReadLine()

let words = [0..N-1] |> Seq.map Reader 

Solution

  • If I had to read given numbers of given types, I would write something like

    open System
    
    let read parser =
        Seq.initInfinite (fun _ -> Console.ReadLine())
        |> Seq.choose (parser >> function true, v -> Some v | _ -> None)
    

    which can then be used

    let ints = read Int32.TryParse
    let ``ten floats`` = read Double.TryParse |> Seq.take 10
    

    Note that if the seq is used multiple times, ReadLine() is called again:

    let anInt = ints |> Seq.take 1
    printfn "%A" anInt
    printfn "%A" anInt // need to input an int again
    

    which can be treated by using e.g. List or Seq.cache.

    For strings, which never fail, use

    let strings = read (fun s -> true, s)
    

    if you have a minimum length requirement:

    let potentialPasswords = read (fun s -> s.Length > 10, s)