使用2个序列的Seq.map应用于采用2个参数的方法

问题描述

| 我正在编写一个快速的数据库性能测试,并选择了F#,以便可以进行更多练习。 我创建了一个方法
measureSelectTimes
,它的签名为
Guid list * Guid list -> IDbCommand -> TimeSpan * TimeSpan
。 然后,我称它为:
let runTests () =
    let sqlCeConn : IDbConnection = initSqlCe() :> IDbConnection
    let sqlServerConn : IDbConnection = initSqlServer() :> IDbConnection
    let dbsToTest = [ sqlCeConn; sqlServerConn ]
    let cmds : seq<IDbCommand> = dbsToTest |> Seq.map initSchema
    let ids : seq<Guid list * Guid list> = cmds |> Seq.map loadData
    let input = Seq.zip ids cmds
    let results = input |> Seq.map (fun i -> measureSelectTimes (fst i) (snd i))
    // ...
我已经明确注释了要澄清的类型。 我不知道如何在没有lambda的情况下调用
measureSelectTimes
。我想像这样部分地应用
ids
ids |> Seq.map measureSelectTimes
,但是我不知道该如何处理结果部分应用的函数,然后映射到
cmds
。这是什么语法?     

解决方法

您可以使用
Seq.map2
Seq.map2 measureSelectTimes ids cmds
要么
(ids,cmds) ||> Seq.map2 measureSelectTimes
    ,您的
measureSelectTimes
函数将两个参数作为单独的参数,但是您需要一个将它们作为元组的函数。一种选择是仅将函数更改为采用元组(如果对参数进行元组化是合乎逻辑的)。 或者,您可以编写一个合并器,将一个带有两个参数的函数转换为一个带有元组的函数。通常称为
uncurry
,它以某种功能性语言存在:
let uncurry f (a,b) = f a b
然后您可以编写:
input |> Seq.map (uncurry measureSelectTimes)
对于像这样的简单用法,这看起来还可以,但是我认为在F#中过多使用组合器不是一个好主意,因为它会使经验不足的函数式程序员难以阅读代码。我可能会这样写(因为我发现它更具可读性):
[ for (time1,time2) in input -> measureSelectTimes time1 time2 ]
    ,一种方法是将“ 0”的签名更改为
(Guid list * Guid list) * IDbCommand -> TimeSpan * TimeSpan
然后您可以将the17ѭ呼叫更改为
let results = input |> Seq.map measureSelectTimes
// or
let results = Seq.map measureSelectTimes input
    

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...