Skip to content

Instantly share code, notes, and snippets.

@Lakret
Created February 1, 2012 03:13
Show Gist options
  • Save Lakret/1714875 to your computer and use it in GitHub Desktop.
Save Lakret/1714875 to your computer and use it in GitHub Desktop.
Very simple typeclasses simulation in F#
open System
open System.Collections.Generic
type Light =
| Green
| Yellow
| Red
//order operations for Light
let dictOfOps =
dict [
"next",
function
| Green -> Yellow
| Yellow -> Red
| Red -> Green
"prec",
function
| Green -> Red
| Yellow -> Green
| Red -> Yellow
]
//order operations for int
let dictOfOpsForInt =
dict [
"next", (+) 1
"prec", fun x -> x - 1
]
//we use dictionary d as a source of concrete implementations of typeclass operations
let orderedFun (elem : 'a) (d : IDictionary<string,('a -> 'a)>) =
//check if "typeclass" match
if (d.ContainsKey "next") && (d.ContainsKey "prec") then
let next = d.["next"]
let prec = d.["prec"]
elem |> next |> next |> prec
else
failwith "d must contain 'next' and 'prec' methods"
let res1 = orderedFun Red dictOfOps
let res2 = orderedFun 1 dictOfOpsForInt
//group "typeclass"
//using dict<string, obj> due nonconformant types
let intsAsGroup =
dict [
"op", box <| (+)
"identity", box <| 0
"inverse", box <| fun x -> -x
]
let trivialGroup =
dict [
"op", box <| fun (_ : char) (_ : char) -> 'e'
"identity", box <| 'e'
"inverse", box <| fun (_ : char) -> 'e'
]
let findInverse (x:'a) (groupOps : IDictionary<_,_>) =
//"typeclass check"
if groupOps.Keys.All(fun x -> (x = "op") || (x = "identity") || (x = "inverse")) then
let (inverse : 'a -> 'a) = groupOps.["inverse"] |> unbox
inverse x
else
failwith "groupOps must contain 'op', 'identity' and 'inverse'"
//let op : int -> int -> int = intsAsGroup.["op"] |> unbox
let devilInv = findInverse 666 intsAsGroup
let trivialInv = findInverse 'e' trivialGroup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment