Reputation: 11649
consider i have the following code,
let sqx= seq [1; 2; 3; 4;]
let sqy= seq [1; 2; 3; 4;]
let func sqx sqy = seq{
for x in sqx do
for y in sqy do yield x,y }
let cartesian sqx sqy= Seq.map (func sqx) sqy
cartesian sqx sqy
at the last line i am facing with the erorr:
The type int is not compatible with type seq<'a>
I have also tried to work with Seq.map2
, but still the same problem.
Upvotes: 0
Views: 1419
Reputation: 52280
My first guess is that you want something like seq [(1, 1); (1, 2); (1, 3); (1, 4); ...]
(which would be the cartesian product of your sqx
and sqy
) and indeed you have this already implemented:
> func sqx sqy;;
val it : seq<int * int> = seq [(1, 1); (1, 2); (1, 3); (1, 4); ...]
but maybe you want to apply some function to all combinations of x in sqx
and y in sqy
? Then can modify your code a bit:
let allWith f sqx sqy =
seq{ for x in sqx do
for y in sqy do
yield f x y }
and have some fun:
> allWith (fun x y -> (x,y)) sqx sqy;;
val it : seq<int * int> = seq [(1, 1); (1, 2); (1, 3); (1, 4); ...]
> allWith (+) sqx sqy;;
val it : seq<int> = seq [2; 3; 4; 5; ...]
or maybe you want to write a function that takes the cartesian product of a sequence of sequences? This is more fun:
let rec cartesian (xss : 'a seq seq) =
if Seq.isEmpty xss then Seq.singleton Seq.empty else
let first = Seq.head xss
let rests = cartesian (Seq.tail xss)
seq { for x in first do
for xs in rests do
yield seq { yield x; yield! xs }
}
here is a simple example:
> cartesian [[1;2;3];[4];[5;6]] |> Seq.toArray;;
val it : seq<int> [] =
[|seq [1; 4; 5]; seq [1; 4; 6]; seq [2; 4; 5]; seq [2; 4; 6]; seq [3; 4; 5];
seq [3; 4; 6]|]
Upvotes: 0
Reputation: 233150
If you look at the types involved, it may help you understand why the compiler complains.
The type of func
is seq<'a> -> seq<'b> -> seq<'a * 'b>
. That is, incidentally, also the type of Seq.zip
; consider replacing func
with Seq.zip
.
The type of Seq.map
is ('a -> 'b) -> seq<'a> -> seq<'b>
.
If you look at cartesian
, it simply it calls Seq.map
with two arguments. The second argument is easiest to think about. From the type of Seq.map
, we know that it must be seq<'something>
.
That also means that func sqx
must fit into the type 'a -> 'b
, or, more specifically 'something -> 'b
.
The type of func sqx
, on the other hand, is seq<'b> -> seq<'a * 'b>
, because it's partially applied. In other words, the input is seq<'b>
.
This must fit into the 'something -> 'b
argument passed to Seq.map
, so 'something
must be seq<'b>
, and the return type is inferred to be seq<'a * 'b>
. Thus, the overall type of cartesian
is seq<'a> -> seq<#seq<'c>> -> seq<seq<'a * 'c>>
.
The first argument to cartesian
must be seq<'a>
. That's OK, because sqx
has the type seq<int>
.
The next argument to cartesian
must be seq<#seq<'c>>
, but sqy
has the type seq<int>
. That's not the same type, and that's the reason cartesian sqx sqy
doesn't compile.
Upvotes: 1