Q:

string representation of F# function signature

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;;
val foo : x:'a -> 'a

Is there a way to retrieve this as a string? The reason I'm asking is that I'm using IfSharp for Jupyter notebooks which doesn't display the signatures, but I'd like to be able to show the types of functions for demonstration purposes.
I've messed around a bit but can't get anything useful, I've tried:
let foo x = (x, x)
printfn "%A" (foo.GetType())
printfn "%A" foo

But this isn't quite what I need:
FSI_0013+clo@3-1
<fun:it@5-2>

Is it possible to access this at all?

A:

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 ())

