Skip to content

Instantly share code, notes, and snippets.

@sgoguen
Created February 5, 2018 15:32
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 sgoguen/af1738c22088b2755680f09accb2046e to your computer and use it in GitHub Desktop.
Save sgoguen/af1738c22088b2755680f09accb2046e to your computer and use it in GitHub Desktop.
FSharp - Functions as Paths
open Microsoft.FSharp.Reflection
let rec listTypes(t:Type) =
[
if FSharpType.IsFunction(t) then
let(a,b) = FSharpType.GetFunctionElements(t)
yield a
if FSharpType.IsFunction(b) then
yield! listTypes(b)
else
yield b
]
open System
type IFuncInfo =
abstract member Name: string
abstract member Types: Type list
abstract member Apply: obj -> obj option
type FuncInfo<'a,'b>(name:string, f:'a -> 'b) =
let types = listTypes(typeof<'a -> 'b>)
member this.Name = name
member this.Types = types
interface IFuncInfo with
member this.Name = name
member this.Types = types
member this.Apply(o) =
match o with
| :? 'a as value -> Some(f(value) :> obj)
| _ -> None
type System.Type with
member this.IsGood = this.Name
let getFunc(name:string, f:'a -> 'b) = FuncInfo(name, f) :> IFuncInfo
//let hasValue = Option.
module Catalog =
let search (catalog:IFuncInfo list) (value:'a)=
[
let t = typeof<'a>
for item in catalog do
match item.Types with
| head::rest when head = t -> yield item
| _ -> ()
]
let apply (catalog:IFuncInfo list) name (value:Result<'a,string>) =
match value with
| Ok(value) ->
Seq.head <| seq { for item in (search catalog value) do
if item.Name = name then
match item.Apply(value) with
| Some(res) -> yield Ok(res)
| None -> ()
yield Error(sprintf "%s not found" name)
}
| Error(msg) -> Error(msg)
let catalog = [
getFunc("isSome", Option.isSome)
getFunc("add1", fun (x:int) -> x + 1)
getFunc("toString", fun (x:int) -> x.ToString())
getFunc("parseInt", fun (x:string) -> int(x))
getFunc("concat", fun (s1:string) (s2:string) -> s1 + s2)
]
let test =
let search = search catalog
let apply = apply catalog
//1 |> search |> Dump
let x = Ok(1) |> apply "add1"
()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment