我正在将基于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实际上为每个参数获取值以及每个函数,所以它会更加有效。即。
func2 (x g) (y h) (z i)
我已经找到了像OCaml一样高效地完成此操作的方法,并且空洞了。 我搜索了unmap,解构,并查看了List
的方法F#可以将值列表直接映射到标识符列表吗?
修改
我转换的代码确实在自己的库中定义了一个map函数。
修改
@OnorioCatenacci这只是我写的一个例子,而不是花费很多时间创建一个真实的工作示例。真正的代码有版权所以我没有完全披露我不能在这里使用它。我试图提出的一点是,我没有为标识符分配常量值,而是为标识符分配函数。我只放入map func1 ["a"; "b"; "c"]
来表明函数是根据需要根据某些输入而不是硬编码生成的。实际代码构建逻辑电路仿真器,返回的函数是不同的逻辑电路;想想组合者。它是自动化定理证明器的一部分。托马斯和丹尼尔理解了这个问题并给出了我用真实代码验证的正确答案。
换句话说,func1 "a"
将使用参数"a"
返回一个函数。 map func1 ['a", "b", "c"]
将返回一系列函数。由于F#中的函数为first-class,因此可以将它们作为值返回。
答案 0 :(得分: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"
答案 1 :(得分: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")