Skip to content

Instantly share code, notes, and snippets.

@hodzanassredin
Last active January 13, 2016 11:02
Show Gist options
  • Save hodzanassredin/2d812e2b4c1f7e53246a to your computer and use it in GitHub Desktop.
Save hodzanassredin/2d812e2b4c1f7e53246a to your computer and use it in GitHub Desktop.
(free)comonoids in fsharp
open System.IO
type CoMonoid<'a> = {destroy : 'a -> unit; clone : 'a -> 'a * 'a}
type FreeComonoid<'a> = 'a
let freeC = {
destroy =fun (c: FreeComonoid<'a>) -> ();
clone = fun (c: FreeComonoid<'a>) -> (c, c)
}
let rec unfold (c:CoMonoid<'a>) (a:'a) =
seq{
let a,a' = c.clone a
yield a
yield! unfold c a'
}
let show10 (c:CoMonoid<'a>) v =
unfold c v
|> Seq.take 10
|> Seq.iter (fun x -> printfn "%A" x)
c.destroy(v)
let intC = {
destroy = fun (a:int) -> ();
clone = fun (a:int) -> (a, a + 1)
}
show10 intC 0
type TextFile = string option * StreamReader
let textFileC = {
destroy = fun (_, r:StreamReader) -> r.Close();
clone = fun (a,r:StreamReader) -> ((a,r), ((if r.EndOfStream then None else Some(r.ReadLine())), r))
}
let openTF (path:string) = snd <| textFileC.clone (Some(""), new StreamReader (path))
show10 textFileC <| openTF "D:\\humanvideo\\create_mongo.cmd"
type Comonoid2<'a> =
| Destroy
| Clone of 'a
type FixComonoid2 = FixC of Comonoid2<FixComonoid2>
let destroy f = f(FixC(Destroy))
let clone a = FixC(Clone(a))
let rec run ast (c : CoMonoid<'a>) (v:'a) =
match ast with
| FixC(Destroy) -> c.destroy(v)
Seq.empty
| FixC(Clone(ast)) -> seq{
let v, v' = c.clone(v)
yield v
yield! run ast c v'
}
let rec cloneTimes count =
if count = 0 then clone
else fun ast -> clone (cloneTimes (count - 1) ast)
let ast = cloneTimes 10 |> destroy
run ast intC 0 |> Seq.iter (fun x -> printfn "cofree int %A" x)
let tfSeq = run ast textFileC (openTF "D:\\humanvideo\\create_mongo.cmd")
tfSeq
|> Seq.map fst
|> Seq.iter (fun x -> printfn "cofree file %A" x)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment