Skip to content

Instantly share code, notes, and snippets.

@panesofglass
Last active August 25, 2017 01:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panesofglass/fd2215da0eef4456a183bd693819c694 to your computer and use it in GitHub Desktop.
Save panesofglass/fd2215da0eef4456a183bd693819c694 to your computer and use it in GitHub Desktop.
inference and builders
type Op =
| Add
| Multiply
static member TryParse input =
match input with
| "add" -> Some Add
| "multiply" -> Some Multiply
| _ -> None
type Command<'a> =
| Command of ('a * 'a -> 'a)
module Command =
type Defaults =
| Defaults
static member Command (command:Command<_>) =
command
static member inline Command op =
Command(fun (x,y) -> match op with Add -> x + y | Multiply -> x * y)
static member inline Command op =
match Op.TryParse op with
| Some op -> Defaults.Command op
| None -> failwithf "invalid operator %s" op
let inline defaults (a: ^a, _: ^b) =
((^a or ^b) : (static member Command: ^a -> Command<_>) a)
let inline infer (x: 'a) =
defaults (x, Defaults)
let (Command f) = Command.infer Add
f(1,2)
let (Command f') = Command.infer "multiply"
f'(2,3)
module Workflow =
[<Sealed>]
type Builder() =
member inline this.Bind(op, f) =
let (Command c) = Command.infer op in f c
member inline this.For(op, f) =
let (Command c) = Command.infer op in f c
[<CustomOperation("apply", MaintainsVariableSpaceUsingBind=true)>]
member inline this.Apply(f, args) = f args
member this.Yield(x) = x
member this.Return(x) = x
let b = Builder()
let inline test op x y =
b {
let! f = op
return f(x,y)
}
let inline test' op x y =
b { for f in op do apply (x,y) }
let inline test'' op x y =
b {
let! f = op
// weird ... applies f
apply (x,y)
}
Workflow.test "add" 1 2
Workflow.test' Multiply 1. 2.
Workflow.test'' (Command(fun (x,y) -> x / y)) 13I 2I
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment