Created
February 5, 2018 15:32
-
-
Save sgoguen/af1738c22088b2755680f09accb2046e to your computer and use it in GitHub Desktop.
FSharp - Functions as Paths
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 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