在 F# 中,无法获取作为带有代码引号的参数传递的函数的名称

Cannot get the name of a function passed as a parameter with code quotations, in F#

我有一个看起来像这样的函数:

let rec retryAsync (retryAttempts: TimeSpan list) (request: unit -> Async<Result<'a, ExchangeError>>) : Async<Result<'a, ExchangeError>> = ....

并且,在出现错误时,我想打印作为“request”传递的函数的名称。它有这个签名:

unit -> Async<Result<'a, ExchangeError>>

我想过使用这样的东西(我在网上找到的代码的略微修改版本):

module DocumentGetter =
    let GetName ([<ReflectedDefinition>]x:Expr<_->_>) =
        match x with
        | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) ->
            methodInfo.Name
        | _ -> "unknown"

但是我得到这个编译错误:

[FS0001] The type 'unit -> Async<Result<'a,ExchangeError>>' is not compatible with the type 'Quotations.Expr<('b -> 'c)>'

如果我传递主函数(retryAsync),我可以得到名字,但是我无法得到传递给它的函数的名字。这是为什么?

基于 ReflectedDefinition 属性隐式转换为 F# 引用不适用于 let 绑定函数,但仅适用于静态成员。以下按预期工作:

type DocumentGetter =
  static member GetName ([<ReflectedDefinition>]x:Expr<_->_>) =
      match x with
      | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) ->
          methodInfo.Name
      | _ -> "unknown"

let rec retryAsync (retryAttempts: TimeSpan list) 
  (request: unit -> Async<Result<'a, ExchangeError>>) 
    : Async<Result<'a, ExchangeError>> = failwith "!"

DocumentGetter.GetName retryAsync

也就是说,我不太确定您对此的设想是什么。听起来您正在尝试做一些非常复杂的事情 - 我认为可能有一种更简单的方法可以在不这样做的情况下解决您的实际问题。