Skip to content

Instantly share code, notes, and snippets.

@atifaziz
Created February 22, 2011 17:13
Show Gist options
  • Save atifaziz/838998 to your computer and use it in GitHub Desktop.
Save atifaziz/838998 to your computer and use it in GitHub Desktop.
open System
type 'a trial =
| Succeeded of 'a
| Failed of string
module Trial =
let get = function
| Succeeded(v) -> v
| Failed(err) -> failwith err
let attempt f =
try Succeeded(f()) with | e -> Failed(e.GetBaseException().Message)
let map f t =
match t with
| Succeeded(v) -> f v
| Failed(_) -> t
module Conversion =
let date s = DateTime.Parse(s)
let int = int
let number = float
let str s = s
module Validate =
let ok _ = None
let that f b a = if not (f a b) then Some("Invalid") else None
let defcol bind map check vs =
let i = bind vs
(fun vs ->
let v = vs |> Seq.nth i
let m = Trial.attempt (fun () -> map v)
m |> Trial.map (fun v -> match check v with
| None -> Succeeded(v)
| Some(err) -> Failed(err)))
type ColumnReference =
| Nth of int
| Named of string
let defcolr = function
| Nth(x) ->
defcol (fun _ -> x)
| Named(n) ->
defcol (Seq.findIndex (fun e -> n.Equals(e, StringComparison.OrdinalIgnoreCase)))
let ( *** ) a b record = record |> a, record |> b
let detable schema f records =
let records = records |> Seq.cache
let schema = records |> Seq.head |> schema |> f
records |> Seq.skip 1 |> Seq.map schema
let schema = (defcolr (Named("DATE" )) Conversion.date (Validate.ok ))
*** (defcolr (Nth (1 )) Conversion.int (Validate.that (> ) 0 ))
*** (defcolr (Named("PRICE")) Conversion.number (Validate.that (>=) 0.0))
let records = seq {
yield ["DATE" ; "HOUR"; "PRICE"]
yield ["2010-01-01"; "08" ; "1.234"]
yield ["2010-01-01"; "12" ; "2.345"]
yield ["2010-01-02"; "08" ; "3.456"]
yield ["2010-01-02"; "12" ; "4.567"]
yield ["2010-01-03"; "08" ; "5.678"]
}
records |> detable schema (fun (date, (hour, price)) -> date *** hour *** price)
|> Seq.map (fun (date, (hour, price)) -> date, hour, price)
|> Seq.iter (printfn "%A")
printfn "---------------------"
records |> detable schema (fun (date, (hour, price)) -> date *** hour *** price)
|> Seq.iter (fun (date, (hour, price)) -> printfn "%A %02d %f" date (hour |> Trial.get) (price |> Trial.get))
printfn "---------------------"
records |> detable schema (fun (date, (hour, price)) -> date *** hour *** price)
|> Seq.map (fun (date, (hour, price)) -> date, hour |> Trial.get, price |> Trial.get)
|> Seq.iter (fun (date, hour, price ) -> printfn "%A %02d %f" date hour price)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment