我有一个带两个列表并生成笛卡尔积的函数。
let cartesian xs ys = xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
我的问题是我传递了两个Int64类型的列表,我收到错误,因为该函数需要两个Int32类型的列表。
如何明确设置列表类型?
答案 0 :(得分:5)
在其中一个参数中添加类型注释应该有效:
let cartesian (xs: int64 list) ys =
xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
或者,使用inline
推断呼叫站点的类型:
let inline cartesian xs ys =
xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
> cartesian [1;2;3] [1;2;3];;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
> cartesian [1L;2L;3L] [1L;2L;3L];;
val it : int64 list = [1L; 2L; 3L; 2L; 4L; 6L; 3L; 6L; 9L]
答案 1 :(得分:4)
扩展注释:存在第三种选择,分解引入约束的代码部分。因为F#乘法运算符具有签名
val inline ( * ) : ^T1 -> ^T2 -> ^T3 when (^T1 or ^T2) : (static member (*) : ^T1 * ^T2 -> ^T3)
除非显示的代码是内联标记,否则不能推广其静态成员约束。将操作员移动到呼叫站点:
let cartesian f xs ys =
List.collect (fun x -> List.map (f x) ys) xs
// val cartesian : f:('a -> 'b -> 'c) -> xs:'a list -> ys:'b list -> 'c list
cartesian (*) [1L..3L] [1L..3L]
// val it : int64 list = [1L; 2L; 3L; 2L; 4L; 6L; 3L; 6L; 9L]