string representation of F# function signature

后端 未结 2 1508
-上瘾入骨i
-上瘾入骨i 2021-01-11 20:27

When I\'m working in the F# REPL fsharpi whenever I enter a new function the signature is printed after I\'ve entered them:

> let foo x = x;;         


        
相关标签:
2条回答
  • 2021-01-11 21:12

    You can analyze types representing F# functions, with the help of the Microsoft.FSharp.Reflection namespace. There is the caveat that generic function arguments default to System.Object, and that other F# types which may form incomplete patterns (e.g. union cases, records) are not included.

    open Microsoft.FSharp.Reflection
    let funString o =
        let rec loop nested t =
            if FSharpType.IsTuple t then
                FSharpType.GetTupleElements t
                |> Array.map (loop true)
                |> String.concat " * "
            elif FSharpType.IsFunction t then
                let fs = if nested then sprintf "(%s -> %s)" else sprintf "%s -> %s"
                let domain, range = FSharpType.GetFunctionElements t
                fs (loop true domain) (loop false range)
            else
                t.FullName
        loop false (o.GetType())
    
    let foo x = x
    funString foo
    // val it : string = "System.Object -> System.Object"
    
    0 讨论(0)
  • 2021-01-11 21:26

    AFAIK, there's no function in FSharp.Core for getting a type's string representation as it would appear to the compiler (though maybe there's something in FSharp.Compiler.Services -- I haven't checked). Here's a small function that works for most simple uses:

    open System
    
    let (|TFunc|_|) (typ: Type) =
        if typ.IsGenericType && typ.GetGenericTypeDefinition () = typeof<int->int>.GetGenericTypeDefinition () then
            match typ.GetGenericArguments() with
            | [|targ1; targ2|] -> Some (targ1, targ2)
            | _ -> None
        else
            None
    
    let rec typeStr (typ: Type) =
        match typ with
        | TFunc (TFunc(_, _) as tfunc, t) -> sprintf "(%s) -> %s" (typeStr tfunc) (typeStr t)
        | TFunc (t1, t2) -> sprintf "%s -> %s" (typeStr t1) (typeStr t2)
        | typ when typ = typeof<int> -> "int"
        | typ when typ = typeof<string> -> "string"
        | typ when typ.IsGenericParameter -> sprintf "'%s" (string typ)
        | typ -> string typ
    
    
    typeStr typeof<(string -> (string -> int) -> int) -> int>
    // val it: string = "string -> (string -> int) -> int"
    typeStr (typeof<int->int>.GetGenericTypeDefinition())
    // val it: string = "'T -> 'TResult"
    

    You can easily write a function on top of this to use typeStr on a value's type:

    let valTypeString x = typStr (x.GetType ())
    
    0 讨论(0)
提交回复
热议问题