F#函数签名的字符串表示

Sea*_*ean 8 f# let jupyter

当我在fsharpi输入新功能时使用F#REPL 时,签名在我输入之后打印:

> let foo x = x;;
val foo : x:'a -> 'a
Run Code Online (Sandbox Code Playgroud)

有没有办法将其作为字符串检索?我问的原因是我正在使用不显示签名的Jupyter笔记本的IfSharp,但我希望能够显示用于演示目的的函数类型.

我已经搞砸了一些但是无法获得任何有用的东西,我试过了:

let foo x = (x, x)
printfn "%A" (foo.GetType())
printfn "%A" foo
Run Code Online (Sandbox Code Playgroud)

但这不是我需要的:

FSI_0013+clo@3-1
<fun:it@5-2>
Run Code Online (Sandbox Code Playgroud)

是否可以访问它?

Jwo*_*sty 5

AFAIK,FSharp.Core 中没有用于获取类型的字符串表示的函数,因为它会出现在编译器中(尽管 FSharp.Compiler.Services 中可能有一些东西——我还没有检查过)。这是一个适用于大多数简单用途的小函数:

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"
Run Code Online (Sandbox Code Playgroud)

您可以轻松地在此之上编写一个函数以用于typeStr值的类型:

let valTypeString x = typStr (x.GetType ())
Run Code Online (Sandbox Code Playgroud)