Skip to content

Instantly share code, notes, and snippets.

@mattpodwysocki
Created April 4, 2009 01:28
Show Gist options
  • Save mattpodwysocki/90075 to your computer and use it in GitHub Desktop.
Save mattpodwysocki/90075 to your computer and use it in GitHub Desktop.
#light
module Option =
let some (n:'b) (f:'a -> 'b) (opt:'a option) : 'b =
match n, f, opt with
| n, _, None -> n
| _, f, Some x -> f x
module Map =
/// Inserts into the Map with the given function if already exists, else adds
let insertWith (f:'a -> 'a -> 'a) (k:'tkey) (v:'a) (m:Map<'tkey, 'a>) =
match Map.tryfind k m with
| None -> Map.add k v m
| Some x -> let res = f v x
Map.add k res m
let alter (f:'a option -> 'a option) (k:'k) (m:Map<'k,'a>) : Map<'k,'a> =
match Map.tryfind k m with
| None ->
match f None with
| None -> m
| Some x -> Map.add k x m
| Some(v) as vo ->
match f vo with
| Some x -> Map.add k x m
| None -> Map.remove k m
let map' (f:'a -> 'b) : Map<'k, 'a> -> Map<'k, 'b> =
Map.mapi (fun k v -> f v)
module SlopeOne =
type Rating<'a> = Map<'a, float>
type SlopeOne<'a> = Map<'a, Map<'a, (int * float)>>
let addT (a, b) (c, d) = (a+c, b+d)
let update (s:SlopeOne<'a>) : Rating<'a> list -> SlopeOne<'a> =
let norm (a:int, b:float) = (a, b / float a)
let update' s rm =
let rs = Map.to_seq rm
let prod = [for (a, m) in rs do for(b, n) in rs -> ((a, b), (1, m - n))]
let insert m (a:'a, b:'a) (v:int * float) =
let foo = Some << Option.some (Map.add b v Map.empty) (Map.insertWith addT b v)
Map.alter foo a m
Seq.fold(fun m (k, v) -> insert m k v) s prod
Map.map' (Map.map' norm) << Seq.fold update' s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment