F# 中的动态函数

Nat*_*son 4 f#

对于无法使用静态类型系统表达某些功能的情况,我正在尝试探索 F# 的动态功能。因此,我正在尝试mapN为(比如说)Option类型创建一个函数,但是我在创建一个具有动态参数数量的函数时遇到了麻烦。我试过了:

let mapN<'output> (f : obj) args =
  let rec mapN' (state:obj) (args' : (obj option) list) = 
    match args' with
    | Some x :: xs -> mapN' ((state :?> obj -> obj) x) xs
    | None _ :: _ -> None
    | [] -> state :?> 'output option

  mapN' f args

let toObjOption (x : #obj option) = 
  Option.map (fun x -> x :> obj) x

let a = Some 5
let b = Some "hi"
let c = Some true

let ans = mapN<string> (fun x y z -> sprintf "%i %s %A" x y z) [a |> toObjOption; b |> toObjOption; c |> toObjOption]
Run Code Online (Sandbox Code Playgroud)

(它接受传入的函数并一次应用一个参数)它编译,但在运行时我得到以下信息:

System.InvalidCastException: Unable to cast object of type 'ans@47' to type 
'Microsoft.FSharp.Core.FSharpFunc`2[System.Object,System.Object]'.
Run Code Online (Sandbox Code Playgroud)

我意识到为选项创建计算表达式或map2通过map5左右定义会更惯用,但我特别想探索 F# 的动态功能,看看这样的事情是否可行。

这只是一个不能在 F# 中完成的概念,还是我缺少一种方法?

The*_*Fox 5

我认为你只能通过反思来采取这种方法。

但是,还有其他方法可以解决整个问题,而无需动态处理或使用您提到的其他静态选项。您可以使用 获得很多相同的便利Option.apply,您需要自己定义(或从库中获取)。这段代码是从F# 中窃取和改编的,目的是为了好玩和获利

module Option =
    let apply fOpt xOpt = 
        match fOpt,xOpt with
        | Some f, Some x -> Some (f x)
        | _ -> None

let resultOption =  
    let (<*>) = Option.apply

    Some (fun x y z -> sprintf "%i %s %A" x y z)
    <*> Some 5
    <*> Some "hi"
    <*> Some true
Run Code Online (Sandbox Code Playgroud)