4

我正在将几个基于 OCaml 的模块转换为 F# 并遇到类似这样的情况

let [x; y; z] = map func1 ["a"; "b"; "c"]

其中 [x; y; z]是标识符列表并 map func1 ["a"; "b"; "c"]返回函数列表。

目前我将列表中的每个值分别绑定到标识符,即

let fList = map func1 ["a"; "b"; "c"]
let x = fList.[0]
let y = fList.[1]
let z = fList.[2]

标识符的使用是为了第二个功能,即

func2 x y z 

我知道我可以修改 func2 以接受一个列表,但由于 func2 实际上需要值以及每个参数的每个函数,所以它会更有效。IE

func2 (x g) (y h) (z i)

我一直在寻找像 OCaml 一样有效地做到这一点的方法,但结果一无所获。我搜索了 unmap,解构,并查看了List的方法

F# 可以将值列表直接映射到标识符列表吗?

编辑

我正在转换的代码确实在它自己的库中定义了一个映射函数。

编辑

@OnorioCatenacci 这只是我写的一个例子,而不是试图花很多时间来创建一个真正的工作例子。真正的代码有版权,所以我不能在没有完全公开的情况下在这里使用它。我试图说明的一点是,我没有将常量值分配给标识符,而是将函数分配给标识符。我只是map func1 ["a"; "b"; "c"]为了表明这些函数是根据一些输入根据需要生成的,而不是硬编码的。真实代码构建逻辑电路模拟器,返回的函数是不同的逻辑电路;认为组合器。它都是自动定理证明器的一部分。Tomas 和 Daniel 理解了这个问题并给出了我用真实代码验证的正确答案。

换句话说func1 "a",将使用参数返回一个函数"a"map func1 ['a", "b", "c"]将返回一个函数列表。由于函数在 F# 中是一等的,因此它们可以作为值返回。

4

2 回答 2

7

您可以将映射应用于列表,然后使用模式匹配将元素绑定到 F# 中的标识符。语法与您编写的示例完全相同:

let [x; y; z] = List.map func1 ["a"; "b"; "c"] 

此示例的唯一问题是 F# 编译器无法静态验证结果是否为长度为 3 的列表,因此它会向您发出警告说“此表达式上的模式匹配不完整”。在这个例子中,它实际上不会发生,但是如果你重新定义map不正确,以至于它会丢弃第一个元素,代码就会中断。

这只是一个警告,所以你可以忽略它,但如果你想避免它,你需要match在意外情况下使用并抛出一些自定义异常:

match List.map func1 ["a"; "b"; "c"] with
| [x; y; z] ->
   // Continue here if the pattern matching does not fail
   func2 (x g) (y h) (z i) 
| _ -> invalidOp "Pattern matching failed"
于 2012-05-09T15:47:40.643 回答
6

如果您想避免 Tomas 提到的“不完整模式匹配”警告,您可以使用具有固定长度的元组并定义您自己的map函数:

module Tuple3 =
  let map f (a, b, c) = (f a, f b, f c)

let x, y, z = Tuple3.map func1 ("a", "b", "c")
于 2012-05-09T16:07:48.347 回答