在很多情况下我都遇到了F#的困难.我相信我没有抓住一些基本概念.我希望有人可以追踪我的推理,并找出我所缺少的(可能很多)事情.
说我正在使用Xunit.我想做的是,提供两个列表,Assert.Equal成对应用方法.例如:
Open Xunit
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 Assert.Equal test1 test2
Run Code Online (Sandbox Code Playgroud)
编译器抱怨该函数Equal不带一个参数.据我所知,不map2应该提供2个参数?
作为一个完整性检查,我在f#immediate中使用以下代码:
let doequal = fun x y -> printf "result: %b\n" (x = y)
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 doequal test1 test2;;
Run Code Online (Sandbox Code Playgroud)
这似乎完全相同. doequal是一个带有两个通用参数和返回单位的lambda . List.map2将每个参数成对地交给lambda,我得到了我预期的输出:
result: true
result: true
result: false
Run Code Online (Sandbox Code Playgroud)
什么给出了什么?来源节目Xunit.Equal有签名public static void Equal<T>(T expected, T actual).为什么我的参数不会映射到方法签名上?
EDIT ONE 我认为两个变量x和y与一个元组(x,y)可以互换地构造和解构.所以我尝试了两个选项,得到了不同的结果.似乎第二个可能比第一个更进一步.
List.map2 Assert.Equal(test1, test2)
编译器现在抱怨"连续的参数应该是空格或tupled"
List.map2(Assert.Equal(test1, test2))
编译器现在抱怨'无法确定一个独特的重载方法......可能需要一个类型注释'
我认为问题的一部分来自混合方法(OO风格)和功能(FP风格).
F#编译器尝试处理这两种方法,但偶尔需要一些帮助.
一种方法是使用FP函数"包装"OO方法.
// wrap method call with function
let assertEqual x y = Assert.Equal(x,y)
// all FP-style functions
List.map2 assertEqual test1 test2
Run Code Online (Sandbox Code Playgroud)
如果您不创建辅助函数,则在使用lambda调用"inline"方法时,通常需要将多个函数参数转换为一个元组:
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2
Run Code Online (Sandbox Code Playgroud)
当您在一行中混合方法和函数时,通常会得到"连续参数应该分开"错误.
printfn "%s" "hello".ToUpper()
// Error: Successive arguments should be separated
// by spaces or tupled
Run Code Online (Sandbox Code Playgroud)
这告诉你编译器有问题需要一些帮助!
您可以通过方法调用附加额外的问题来解决这个问题:
printfn "%s" ("hello".ToUpper()) // ok
Run Code Online (Sandbox Code Playgroud)
或者有时,使用反向管道:
printfn "%s" <| "hello".ToUpper() // ok
Run Code Online (Sandbox Code Playgroud)
无论如何,包装方法通常都值得做,以便您可以交换参数以使其更适合部分应用:
// wrap method call with function AND swap params
let contains searchFor (s:string) = s.Contains(searchFor)
// all FP-style functions
["a"; "b"; "c"]
|> List.filter (contains "a")
Run Code Online (Sandbox Code Playgroud)
请注意,在最后一行中,我不得不使用parens优先于contains "a"overList.filter
public static void Equal<T>(T expected, T actual)
Run Code Online (Sandbox Code Playgroud)
不带两个参数 - 它需要一个参数,这是一个带有两个元素的元组:(T expected, T actual).
试试这个:
List.map2 Assert.Equal(test1, test2)
Run Code Online (Sandbox Code Playgroud)