Created
February 1, 2012 03:13
-
-
Save Lakret/1714875 to your computer and use it in GitHub Desktop.
Very simple typeclasses simulation in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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