views:

95

answers:

2

Hi,

why does not this code work?

type Test() =
  static member func (a: seq<'a seq>) = 5.

let a = [[4.]]
Test.func(a)

It gives following error:

The type 'float list list' is not compatible with the type 'seq<seq<'a>>'
+4  A: 

The error message describes the problem -- in F#, list<list<'a>> isn't compatible with seq<seq<'a>>.

The upcast function helps get around this, by making a into a list<seq<float>>, which is then compatible with seq<seq<float>>:

let a = [upcast [4.]]
Test.func(a)

Edit: You can make func more flexible in the types it accepts. The original accepts only sequences of seq<'a>. Even though list<'a> implements seq<'a>, the types aren't identical, and the compiler gives you an error.

However, you can modify func to accept sequences of any type, as long as that type implements seq<'a>, by writing the inner type as #seq:

type Test() =
  static member func (a: seq<#seq<'a>>) = 5.

let a = [[4.]]
Test.func(a) // works
Tim Robinson
And why is it so? If you write "let func (a: seq<'a seq>) = 5." then it works without any upcasting.
Oldrich Svec
I get the same error -- http://gist.github.com/497844
Tim Robinson
My mistake. You are right. Do you have any explanation why for 'let func (a : float seq) = 5.' we do not have to do upcasting and for seq seq we have to do that?
Oldrich Svec
`seq<'a>` and `seq<'b>` are fundamentally different types in F#, even if you (as the programmer) know that any `'b` and be converted to `'a`. You have to do the conversion in the code by hand; in this case, with `upcast`. But see my edited answer...
Tim Robinson
Thanks a lot for your help. Now I understand it a little more.
Oldrich Svec
+5  A: 

Change your code to

type Test() = 
  static member func (a: seq<#seq<'a>>) = 5. 

let a = [[4.]] 
Test.func(a) 

The trick is in the type of a. You need to explicitly allow the outer seq to hold instances of seq<'a> and subtypes of seq<'a>. Using the # symbol enables this.

Alex Humphrey