I have a function that takes two lists and generates a Cartesian product.
let cartesian xs ys = xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
My problem is I am passing two lists of type Int64, and I am getting errors because the function is expecting two lists of type Int32.
How does one explicitly set the list type?
Adding a type annotation to one of the arguments should work:
let cartesian (xs: int64 list) ys =
xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
Alternatively, use inline
to infer types at call site:
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]
Extended comment: A third alternative exists, factoring out the part of the code which introduces the constraint. Because the F# multiplication operator has the signature
val inline ( * ) : ^T1 -> ^T2 -> ^T3 when (^T1 or ^T2) : (static member (*) : ^T1 * ^T2 -> ^T3)
its static member constraint cannot be generalized unless the code in which it appears is marked inline. Move the operator to the call site:
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With