Skip to content

Instantly share code, notes, and snippets.

@palladin
Created December 26, 2015 19:26
Show Gist options
  • Save palladin/4a05b31dcf5576c5dd69 to your computer and use it in GitHub Desktop.
Save palladin/4a05b31dcf5576c5dd69 to your computer and use it in GitHub Desktop.
Type-level Fold
type Bool = interface end
and True = True with
static member inline (|*|) (f, True) = (BoolFold ? (f) <- True)
interface Bool
and False = False with
static member inline (|*|) (f, False) = (BoolFold ? (f) <- False)
interface Bool
and And<'a, 'b when 'a :> Bool and 'b :> Bool> = And of 'a * 'b with
static member inline (|*|) (f, x) = (BoolFold ? (f) <- x)
interface Bool
and Or<'a, 'b when 'a :> Bool and 'b :> Bool> = Or of 'a * 'b with
static member inline (|*|) (f, x) = (BoolFold ? (f) <- x)
interface Bool
and Not<'a when 'a :> Bool> = Not of 'a with
static member inline (|*|) (f, x) = (BoolFold ? (f) <- x)
interface Bool
and BoolFold = BoolFold with
static member inline (?<-) (BoolFold, f, True) = f $ True
static member inline (?<-) (BoolFold, f, False) = f $ False
static member inline (?<-) (BoolFold, f, And(a, b)) =
let app = And (f |*| a, f |*| b)
f $ app
static member inline (?<-) (BoolFold, f, Or(a, b)) =
let app = Or (f |*| a, f |*| b)
f $ app
static member inline (?<-) (BoolFold, f, Not(a)) =
let app = Not (f |*| a)
f $ app
type Eval = Eval with
static member inline ($) (Eval, True) = True
static member inline ($) (Eval, False) = False
static member inline ($) (Eval, And(True, True)) = True
static member inline ($) (Eval, And(True, False)) = False
static member inline ($) (Eval, And(False, True)) = False
static member inline ($) (Eval, And(False, False)) = False
static member inline ($) (Eval, Or(True, True)) = True
static member inline ($) (Eval, Or(True, False)) = True
static member inline ($) (Eval, Or(False, True)) = True
static member inline ($) (Eval, Or(False, False)) = False
static member inline ($) (Eval, Not(True)) = False
static member inline ($) (Eval, Not(False)) = True
type BitFlip = BitFlip with
static member inline ($) (BitFlip, True) = False
static member inline ($) (BitFlip, False) = True
static member inline ($) (BitFlip, And(x, y)) = And(x, y)
static member inline ($) (BitFlip, Or(x, y)) = Or(x, y)
static member inline ($) (BitFlip, Not(x)) = Not(x)
let (<&>) a b = And (a, b)
let (<|>) a b = Or (a, b)
let inline fold f (x : ^R) = (BoolFold ? (f) <- x)
//// Examples
let t = fold BitFlip False // t : True
let f = fold BitFlip True // f : False
let a = fold BitFlip (True <&> False) // And<False,True>
let e = fold Eval (True <&> False) // e : False
let n = fold Eval (True <|> False) // n : True
let k = fold Eval (Not True <|> False) // k : False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment