This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Alias to flatMap

3 replies
Fabio Cechinel ...
Joined: 2009-04-23,
User offline. Last seen 42 years 45 weeks ago.

Hello All,

I'm trying to use implicit conversion to "add" an kind of alias method
to flatMap on Traversables of a specific type. The idea is to create a
more meaningful syntax to my libraries.

So I'm trying to do something like that (note that i have changed some
types just to remove external references):

[code]
implicit def add2list[T <: GenTraversable[Int]](t: T):
MyRichTraversable[T] = new MyRichTraversable(t)

class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
def \\[That](foo: Int)(implicit bf: CanBuildFrom[T, Int, That]): That = {
t.flatMap( i => List(i, foo) )(bf)
}
}
[/code]

So, here, i'm trying to add '\\' method to GenTraversable[Int] and
subtypes. But compiler is given the following error:

type mismatch; found :
scala.collection.generic.CanBuildFrom[T,Int,That] required:
scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[Int],Int,That]

I don't know why it is complaining about T since it is a subtype of
GenTraversable[Int].

Does anyone why i'm doing wrong? how can i can make this work?

AlanP
Joined: 2011-05-31,
User offline. Last seen 42 years 45 weeks ago.
Re: Alias to flatMap

Fabio,

CanBuildFrom is contravariant in its first type parameter. This makes
sense as it represents the original collection type, and if the
compiler can't find a CBF for the exact collection type (invariant),
then you'd be ok using one CBF for a more general supertype
(contravariant), but not the other way around.

For your specific problem, you can actually ignore all that. You can
rely on the implicit CBF captured in the flatMap invocation you do in
your method body. I have rewritten your code with this simplification
and it seems to work fine:

scala> class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
| def \\(foo: Int)= {
| t.flatMap( i => List(i, foo) ) }}
defined class MyRichTraversable

scala> implicit def add2list[T <: GenTraversable[Int]](t:
T):MyRichTraversable[T] = new MyRichTraversable(t)
add2list: [T <: scala.collection.GenTraversable[Int]](t:
T)MyRichTraversable[T]

scala> List(1,2,3).\\(5)
res0: scala.collection.GenTraversable[Int] = List(1, 5, 2, 5, 3, 5)

Regards,

Alan

On Jun 16, 5:02 pm, Fabio Cechinel Veronez
wrote:
> Hello All,
>
> I'm trying to use implicit conversion to "add" an kind of alias method
> to flatMap on Traversables of a specific type. The idea is to create a
> more meaningful syntax to my libraries.
>
> So I'm trying to do something like that (note that i have changed some
> types just to remove external references):
>
> [code]
> implicit def add2list[T <: GenTraversable[Int]](t: T):
> MyRichTraversable[T] = new MyRichTraversable(t)
>
> class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
>     def \\[That](foo: Int)(implicit bf: CanBuildFrom[T, Int, That]): That = {
>         t.flatMap( i => List(i, foo) )(bf)
>     }}
>
> [/code]
>
> So, here, i'm trying to add '\\' method to GenTraversable[Int] and
> subtypes. But compiler is given the following error:
>
> type mismatch;  found   :
> scala.collection.generic.CanBuildFrom[T,Int,That]  required:
> scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[Int], Int,That]
>
> I don't know why it is complaining about T since it is a subtype of
> GenTraversable[Int].
>
> Does anyone why i'm doing wrong? how can i can make this work?
>
> --
> Fabio Cechinel Veronez

Fabio Cechinel ...
Joined: 2009-04-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Alias to flatMap

Hello Alan,

Thank you for your explanation.

I was trying to use CanBuildFrom on that "extension method" so that
'\\' method would return the correct type ( in that case,
List(1,2,3).\\(5) would return List[Int]).

Do you know how could i accomplish that?

On Fri, Jun 17, 2011 at 8:31 PM, AlanP wrote:
> Fabio,
>
> CanBuildFrom is contravariant in its first type parameter. This makes
> sense as it represents the original collection type, and if the
> compiler can't find a CBF for the exact collection type (invariant),
> then you'd be ok using one CBF for a more general supertype
> (contravariant), but not the other way around.
>
> For your specific problem, you can actually ignore all that. You can
> rely on the implicit CBF captured in the flatMap invocation you do in
> your method body. I have rewritten your code with this simplification
> and it seems to work fine:
>
> scala> class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
>     | def \\(foo: Int)= {
>     | t.flatMap( i => List(i, foo) ) }}
> defined class MyRichTraversable
>
> scala> implicit def add2list[T <: GenTraversable[Int]](t:
> T):MyRichTraversable[T] = new MyRichTraversable(t)
> add2list: [T <: scala.collection.GenTraversable[Int]](t:
> T)MyRichTraversable[T]
>
> scala> List(1,2,3).\\(5)
> res0: scala.collection.GenTraversable[Int] = List(1, 5, 2, 5, 3, 5)
>
>
> Regards,
>
> Alan
>
>
> On Jun 16, 5:02 pm, Fabio Cechinel Veronez
> wrote:
>> Hello All,
>>
>> I'm trying to use implicit conversion to "add" an kind of alias method
>> to flatMap on Traversables of a specific type. The idea is to create a
>> more meaningful syntax to my libraries.
>>
>> So I'm trying to do something like that (note that i have changed some
>> types just to remove external references):
>>
>> [code]
>> implicit def add2list[T <: GenTraversable[Int]](t: T):
>> MyRichTraversable[T] = new MyRichTraversable(t)
>>
>> class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
>>     def \\[That](foo: Int)(implicit bf: CanBuildFrom[T, Int, That]): That = {
>>         t.flatMap( i => List(i, foo) )(bf)
>>     }}
>>
>> [/code]
>>
>> So, here, i'm trying to add '\\' method to GenTraversable[Int] and
>> subtypes. But compiler is given the following error:
>>
>> type mismatch;  found   :
>> scala.collection.generic.CanBuildFrom[T,Int,That]  required:
>> scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[Int], Int,That]
>>
>> I don't know why it is complaining about T since it is a subtype of
>> GenTraversable[Int].
>>
>> Does anyone why i'm doing wrong? how can i can make this work?
>>
>> --
>> Fabio Cechinel Veronez

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: Re: Alias to flatMap
You might need to capture the CanBuildFrom "early", meaning in the implicit 'extension' def.  My guess is the type info required for a good CanBuildFrom lookup is getting lost by the time you look for a CanBuildFrom.
It seems like it should work the way you have it.   I'll try to play around with it when I have time.

On Wed, Jun 22, 2011 at 8:52 AM, Fabio Cechinel Veronez <fabio.veronez@gmail.com> wrote:
Hello Alan,

Thank you for your explanation.

I was trying to use CanBuildFrom on that "extension method" so that
'\\' method would return the correct type ( in that case,
List(1,2,3).\\(5) would return List[Int]).

Do you know how could i accomplish that?


On Fri, Jun 17, 2011 at 8:31 PM, AlanP <alanpog@gmail.com> wrote:
> Fabio,
>
> CanBuildFrom is contravariant in its first type parameter. This makes
> sense as it represents the original collection type, and if the
> compiler can't find a CBF for the exact collection type (invariant),
> then you'd be ok using one CBF for a more general supertype
> (contravariant), but not the other way around.
>
> For your specific problem, you can actually ignore all that. You can
> rely on the implicit CBF captured in the flatMap invocation you do in
> your method body. I have rewritten your code with this simplification
> and it seems to work fine:
>
> scala> class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
>     | def \\(foo: Int)= {
>     | t.flatMap( i => List(i, foo) ) }}
> defined class MyRichTraversable
>
> scala> implicit def add2list[T <: GenTraversable[Int]](t:
> T):MyRichTraversable[T] = new MyRichTraversable(t)
> add2list: [T <: scala.collection.GenTraversable[Int]](t:
> T)MyRichTraversable[T]
>
> scala> List(1,2,3).\\(5)
> res0: scala.collection.GenTraversable[Int] = List(1, 5, 2, 5, 3, 5)
>
>
> Regards,
>
> Alan
>
>
> On Jun 16, 5:02 pm, Fabio Cechinel Veronez <fabio.vero...@gmail.com>
> wrote:
>> Hello All,
>>
>> I'm trying to use implicit conversion to "add" an kind of alias method
>> to flatMap on Traversables of a specific type. The idea is to create a
>> more meaningful syntax to my libraries.
>>
>> So I'm trying to do something like that (note that i have changed some
>> types just to remove external references):
>>
>> [code]
>> implicit def add2list[T <: GenTraversable[Int]](t: T):
>> MyRichTraversable[T] = new MyRichTraversable(t)
>>
>> class MyRichTraversable[T <: GenTraversable[Int]](t: T) {
>>     def \\[That](foo: Int)(implicit bf: CanBuildFrom[T, Int, That]): That = {
>>         t.flatMap( i => List(i, foo) )(bf)
>>     }}
>>
>> [/code]
>>
>> So, here, i'm trying to add '\\' method to GenTraversable[Int] and
>> subtypes. But compiler is given the following error:
>>
>> type mismatch;  found   :
>> scala.collection.generic.CanBuildFrom[T,Int,That]  required:
>> scala.collection.generic.CanBuildFrom[scala.collection.GenTraversable[Int], Int,That]
>>
>> I don't know why it is complaining about T since it is a subtype of
>> GenTraversable[Int].
>>
>> Does anyone why i'm doing wrong? how can i can make this work?
>>
>> --
>> Fabio Cechinel Veronez



--
Fabio Cechinel Veronez

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland