Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one specify a list type in a function parameter?

Tags:

f#

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?

like image 704
Mike Henderson Avatar asked Jan 03 '23 15:01

Mike Henderson


2 Answers

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]
like image 69
Taylor Wood Avatar answered Jan 19 '23 01:01

Taylor Wood


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]
like image 45
kaefer Avatar answered Jan 19 '23 03:01

kaefer