Skip to content

Instantly share code, notes, and snippets.

@vasily-kirichenko
Last active Mar 21, 2016
Embed
What would you like to do?
module Csv
open System.IO
open ExtCore.Control.Collections
let Ok = Choice1Of2
let Fail = Choice2Of2
let (>>=) x y = Choice.bind y x
let (<!>) x y = Choice.mapError y x
let (|ArrayOfLength|) a = Array.length a
type Row = float[]
type Error =
| WrongArgs of string
| CannotReadFile of exn
| WrongRow of Row
| WrongValue of exn
let addTo totals row =
match totals, row with
| [||], _ -> Ok row
| ArrayOfLength a, ArrayOfLength b when a = b -> Ok <| Array.map2 (+) totals row
| _ -> Fail (WrongRow row)
let readFile fileName = Choice.attempt (fun _ -> File.ReadLines fileName) <!> CannotReadFile
let parseRow line =
line
|> String.split [|','|]
|> Choice.Array.map (fun x -> Choice.attempt (fun _ -> float x))
<!> WrongValue
let parseRows = Seq.toList >> Choice.List.map parseRow
let sumRows = Choice.List.fold addTo [||]
let formatRow = Array.map string >> String.concat "," >> sprintf "%s"
[<EntryPoint>]
let main args =
match args with
| [| fileName |] ->
readFile fileName >>= parseRows >>= sumRows
|> Choice.map formatRow
| _ -> Fail (WrongArgs "Exactly 1 filename must be given")
|> printfn "%A"
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment