Kha的回答展示了如何通过直接使用闭包来手动优化代码。如果这是您需要经常使用的频繁模式,也可以定义一个高阶函数,从两个函数构造高效代码 - 第一个函数对某些参数进行预处理,第二个函数执行获得剩余参数后的实际处理。
代码如下所示:
let preProcess finit frun preInput =
let preRes = finit preInput
fun input -> frun preRes input
let f : string list -> ((string -> string) * string) -> bool =
preProcess
Set.ofList // Pre-processing of the first argument
(fun elemsSet (normalize, p) -> // Implements the actual work to be
normalize p |> elemsSet.Contains) // .. done once we get the last argument
这是一个问题,但这是否更优雅......
另一个(疯狂的)想法是您可以为此使用计算表达式。允许您执行此操作的计算构建器的定义非常不标准(这不是人们通常使用它们做的事情,并且与 monad 或任何其他理论没有任何关系)。但是,应该可以这样写:
type CurryBuilder() =
member x.Bind((), f:'a -> 'b) = f
member x.Return(a) = a
let curry = new CurryBuilder()
在curry
计算中,您可以使用let!
来表示您想要获取函数的下一个参数(在评估前面的代码之后):
let f : string list -> (string -> string) -> string -> bool = curry {
let! elems = ()
let elemsSet = Set.ofList elems
printf "elements converted"
let! normalize = ()
let! p = ()
printf "calling"
return normalize p |> elemsSet.Contains }
let ff = f [ "a"; "b"; "c" ] (fun s -> s.ToLower())
// Prints 'elements converted' here
ff "C"
ff "D"
// Prints 'calling' two times
以下是一些资源,其中包含有关计算表达式的更多信息: