如何在函数参数中指定列表类型?

时间:2018-03-24 21:52:06

标签: f#

我有一个带两个列表并生成笛卡尔积的函数。

let cartesian xs ys = xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))

我的问题是我传递了两个Int64类型的列表,我收到错误,因为该函数需要两个Int32类型的列表。

如何明确设置列表类型?

2 个答案:

答案 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]