Skip to content

Instantly share code, notes, and snippets.

@vasily-kirichenko
Last active March 21, 2016 05:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vasily-kirichenko/3c5fadf92ccc5d286946 to your computer and use it in GitHub Desktop.
Save vasily-kirichenko/3c5fadf92ccc5d286946 to your computer and use it in GitHub Desktop.
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