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

Type inference: Scala vs C#

10 replies
hiddenburger
Joined: 2010-07-20,
User offline. Last seen 42 years 45 weeks ago.

Can anybody explain why C# (4.0) example works but Scala (2.8) doesn't ?

C#:

class App {

static void Main(string[] args) {
f(new List() {1, 2, 3}, (x, y) => x > y);
}

static void f(List a, Func g) {
}
}

Scala:

object App {

def main(args: Array[String]) {
f(List[Int](1, 2, 3), _ > _)
}

def f[T](a: List[T], b: (T, T) => Boolean) = {
}
}

error: missing parameter type for expanded function ((x$1, x$2) =>
x$1.$greater(x$2))
f(List[Int](1, 2, 3), _ > _)

Aydjen
Joined: 2009-08-21,
User offline. Last seen 1 year 28 weeks ago.
Re: Type inference: Scala vs C#

Hi,

I can not answer why your example does not work. But this works:

def main(args: Array[String]) {
f[Int](List(1, 2, 3), _ > _)
}

-
Andreas

Am Dienstag, den 20.07.2010, 13:22 +0200 schrieb hiddenburger
:
> Can anybody explain why C# (4.0) example works but Scala (2.8) doesn't ?
>
> C#:
>
> class App {
>
> static void Main(string[] args) {
> f(new List() {1, 2, 3}, (x, y) => x > y);
> }
>
> static void f(List a, Func g) {
> }
> }
>
> Scala:
>
> object App {
>
> def main(args: Array[String]) {
> f(List[Int](1, 2, 3), _ > _)
> }
>
> def f[T](a: List[T], b: (T, T) => Boolean) = {
> }
> }
>
> error: missing parameter type for expanded function ((x$1, x$2) =>
> x$1.$greater(x$2))
> f(List[Int](1, 2, 3), _ > _)

Roshan Dawrani
Joined: 2010-07-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Type inference: Scala vs C#
Hi,
I am very new to Scala, so can't explain well in its type inference theory, but changing it as below makes it compile fine

----------------------------------------------------------------------------------

object App {

   def main(args: Array[String]) {
       f(List[Int](1, 2, 3), (_:Int) > (_:Int))

   }

   def f[T](a: List[T], b: (T, T) => Boolean) = {
   }
}
----------------------------------------------------------------------------------

rgds,
Roshan

On Tue, Jul 20, 2010 at 4:52 PM, hiddenburger <hiddenburger [at] gmail [dot] com> wrote:

Can anybody explain why C# (4.0) example works but Scala (2.8) doesn't ?

C#:

class App {

   static void Main(string[] args) {
       f(new List<int>() {1, 2, 3}, (x, y) => x > y);
   }

   static void f<T>(List<T> a, Func<T, T, Boolean> g) {
   }
}

Scala:

object App {

   def main(args: Array[String]) {
       f(List[Int](1, 2, 3), _ > _)
   }

   def f[T](a: List[T], b: (T, T) => Boolean) = {
   }
}

error: missing parameter type for expanded function ((x$1, x$2) =>
x$1.$greater(x$2))
f(List[Int](1, 2, 3), _ > _)
--
View this message in context: http://scala-programming-language.1934581.n4.nabble.com/Type-inference-Scala-vs-C-tp2295304p2295304.html
Sent from the Scala - User mailing list archive at Nabble.com.

hiddenburger
Joined: 2010-07-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Type inference: Scala vs C#

Thanks for replays but i'm curious exactly about first example.

Why Scala cannot infer second argument type from the first one (as C# do) ?

It's also known that Scala can infer from first argument list like this:

object App {

def main(args: Array[String]) {
f(List[Int](1, 2, 3))( _ > _)
}

def f[T](a: List[T])(b: (T, T) => Boolean) = {
}
}

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 6 days ago.
Re: Re: Type inference: Scala vs C#
The way scala does inference requires you to "help" it out a bit here by letting it infer the type of Int early.  Change your Scala version to the following:
object App {

   def main(args: Array[String]) {
       f(List(1, 2, 3))(_ > _)
   }

   def f[T](a: List[T])(b: (T, T) => Boolean) = {
   }
}
When you use placeholder syntax, Scala needs to know a little bit about the types ahead of time.  It does not use previous parameters to infer future parameters, but does use previous *parameter lists*, hence currying the function should do what you want.
Hope that helps! - Josh

On Tue, Jul 20, 2010 at 7:56 AM, hiddenburger <hiddenburger [at] gmail [dot] com> wrote:

Thanks for replays but i'm curious exactly about first example.

Why Scala cannot infer second argument type from the first one (as C# do) ?

It's also known that Scala can infer from first argument list like this:

object App {

   def main(args: Array[String]) {
       f(List[Int](1, 2, 3))( _ > _)
   }

   def f[T](a: List[T])(b: (T, T) => Boolean) = {
   }
}


--
View this message in context: http://scala-programming-language.1934581.n4.nabble.com/Type-inference-Scala-vs-C-tp2295304p2295357.html
Sent from the Scala - User mailing list archive at Nabble.com.

H-star Development
Joined: 2010-04-14,
User offline. Last seen 2 years 26 weeks ago.
Re: Re: Type inference: Scala vs C#

why doesn't scala infer the type here? even java does.

-------- Original-Nachricht --------
> Datum: Tue, 20 Jul 2010 08:30:26 -0400
> Von: Josh Suereth
> An: hiddenburger
> CC: scala-user [at] listes [dot] epfl [dot] ch
> Betreff: Re: [scala-user] Re: Type inference: Scala vs C#

> The way scala does inference requires you to "help" it out a bit here by
> letting it infer the type of Int early. Change your Scala version to the
> following:
>
> object App {
>
> def main(args: Array[String]) {
> f(List(1, 2, 3))(_ > _)
> }
>
> def f[T](a: List[T])(b: (T, T) => Boolean) = {
> }
> }
>
> When you use placeholder syntax, Scala needs to know a little bit about
> the
> types ahead of time. It does not use previous parameters to infer future
> parameters, but does use previous *parameter lists*, hence currying the
> function should do what you want.
>
> Hope that helps!
> - Josh
>
> On Tue, Jul 20, 2010 at 7:56 AM, hiddenburger
> wrote:
>
> >
> > Thanks for replays but i'm curious exactly about first example.
> >
> > Why Scala cannot infer second argument type from the first one (as C#
> do) ?
> >
> > It's also known that Scala can infer from first argument list like this:
> >
> > object App {
> >
> > def main(args: Array[String]) {
> > f(List[Int](1, 2, 3))( _ > _)
> > }
> >
> > def f[T](a: List[T])(b: (T, T) => Boolean) = {
> > }
> > }
> >
> >
> > --
> > View this message in context:
> >
> http://scala-programming-language.1934581.n4.nabble.com/Type-inference-S...
> > Sent from the Scala - User mailing list archive at Nabble.com.
> >

Vincent
Joined: 2010-01-25,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Type inference: Scala vs C#

The type system of Java is really different from the one of Scala. I
don't know all the possibilities of Scala, but its type system is
really more powerfull.
And there is a trade-off: if your type system is more expressive, type
inference becomes more difficult (it can easily becomes undecidable..
and I think it's already the case for the full scale Scala).

That's why Java manages to infer this type without any help, and why
Scala needs one.
Ask someone else for the differences, I don't know enough about Scala
right now to answer this one :)

V.

2010/7/20 Dennis Haupt :
> why doesn't scala infer the type here? even java does.
>
> -------- Original-Nachricht --------
>> Datum: Tue, 20 Jul 2010 08:30:26 -0400
>> Von: Josh Suereth
>> An: hiddenburger
>> CC: scala-user [at] listes [dot] epfl [dot] ch
>> Betreff: Re: [scala-user] Re: Type inference: Scala vs C#
>
>> The way scala does inference requires you to "help" it out a bit here by
>> letting it infer the type of Int early.  Change your Scala version to the
>> following:
>>
>> object App {
>>
>>    def main(args: Array[String]) {
>>        f(List(1, 2, 3))(_ > _)
>>    }
>>
>>    def f[T](a: List[T])(b: (T, T) => Boolean) = {
>>    }
>> }
>>
>> When you use placeholder syntax, Scala needs to know a little bit about
>> the
>> types ahead of time.  It does not use previous parameters to infer future
>> parameters, but does use previous *parameter lists*, hence currying the
>> function should do what you want.
>>
>> Hope that helps!
>> - Josh
>>
>> On Tue, Jul 20, 2010 at 7:56 AM, hiddenburger
>> wrote:
>>
>> >
>> > Thanks for replays but i'm curious exactly about first example.
>> >
>> > Why Scala cannot infer second argument type from the first one (as C#
>> do) ?
>> >
>> > It's also known that Scala can infer from first argument list like this:
>> >
>> > object App {
>> >
>> >    def main(args: Array[String]) {
>> >        f(List[Int](1, 2, 3))( _ > _)
>> >    }
>> >
>> >    def f[T](a: List[T])(b: (T, T) => Boolean) = {
>> >    }
>> > }
>> >
>> >
>> > --
>> > View this message in context:
>> >
>> http://scala-programming-language.1934581.n4.nabble.com/Type-inference-S...
>> > Sent from the Scala - User mailing list archive at Nabble.com.
>> >
>
> --
> GRATIS für alle GMX-Mitglieder: Die maxdome Movie-FLAT!
> Jetzt freischalten unter http://portal.gmx.net/de/go/maxdome01
>

channingwalton
Joined: 2008-09-27,
User offline. Last seen 2 weeks 1 day ago.
Re: Type inference: Scala vs C#

Josh Suereth wrote:
>
> When you use placeholder syntax, Scala needs to know a little bit about
> the
> types ahead of time. It does not use previous parameters to infer future
> parameters, but does use previous *parameter lists*, hence currying the
> function should do what you want.
>

Thats very useful to know, thanks Josh.

Arthur Peters 2
Joined: 2009-01-10,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Type inference: Scala vs C#

The issue that I see with original example is that scala does typing of parameter lists in one go instead of typing one parameter at a time. That's why splitting the parameter into a new parameter list fixes the problem. But this does leave me wondering why. What disadvantage is there to typing one parameter at a time? I instinctually feel that there would be problems typing functions where the same generic parameter is used in for more than one argument (since if you do it in one go you can find the common parent but if you do it one at a time you couldn't), but its not at all clear in my mind. I'd love to hear discussion on this.

-Arthur (sent from phone)

On Jul 20, 2010 12:56 PM, "Vincent" <vincent [dot] siles [at] gmail [dot] com> wrote:

The type system of Java is really different from the one of Scala. I
don't know all the possibilities of Scala, but its type system is
really more powerfull.
And there is a trade-off: if your type system is more expressive, type
inference becomes more difficult (it can easily becomes undecidable..
and I think it's already the case for the full scale Scala).

That's why Java manages to infer this type without any help, and why
Scala needs one.
Ask someone else for the differences, I don't know enough about Scala
right now to answer this one :)

V.

2010/7/20 Dennis Haupt <h-star [at] gmx [dot] de>:

> why doesn't scala infer the type here? even java does.
>
> -------- Original-Nachricht --------
>>...

adriaanm
Joined: 2010-02-08,
User offline. Last seen 31 weeks 4 days ago.
Re: Re: Type inference: Scala vs C#
I don't know if anyone is maintaining a FAQ, but this would certainly make for a good entry.

On Tue, Jul 20, 2010 at 2:46 PM, Dennis Haupt <h-star [at] gmx [dot] de> wrote:
why doesn't scala infer the type here? even java does.
I think it's time for a Scientific Experiment:
adriaan$ scalaWelcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).Type in expressions to have them evaluated.Type :help for more information.
scala> /*     | Scala interpreter experiments to illustrate that type inference & implicit search go from left-to-right,     | with constraints being solved per argument list (once type variable is solved, later argument list has to abide)      | */
scala> def illustrateInfer[a](x: a, y: a) = error("meh") illustrateInfer: [a](x: a,y: a)Nothing
scala> illustrateInfer(1, "a") // well-typed java.lang.RuntimeException: meh at scal...
scala> def illustrateInferCurry[a](x: a)(y: a) = error("meh")  illustrateInferCurry: [a](x: a)(y: a)Nothing
scala> illustrateInferCurry(1)("a") // ill-typed<console>:7: error: type mismatch; found   : java.lang.String("a")  required: Int       illustrateInferCurry(1)("a") // ill-typed                               ^
scala> trait Coerce[A, B] extends (A => B) // typical type class that will lead to ambiguity defined trait Coerce
scala> implicit object coerceIntFloat extends Coerce[Int, Float]{def apply(x: Int) = x.toFloat}defined module coerceIntFloat
scala> implicit object coerceIntStr extends Coerce[Int, String]{def apply(x: Int) = x.toString} defined module coerceIntStr
scala> // first argument list will fix a and b
scala> def coerce2[a,b](x: a, proto: b)(implicit w: Coerce[a, b]): b = x  coerce2: [a,b](x: a,proto: b)(implicit w: Coerce[a,b])b
scala> coerce2(1, "a") // okres2: java.lang.String = 1
scala> trait MustBeString[B]defined trait MustBeString
scala> implicit object beString extends MustBeString[String] defined module beString
scala> def coerce[a,b](x: a)(implicit w: Coerce[a, b], ws: MustBeString[b]): b = xcoerce: [a,b](x: a)(implicit w: Coerce[a,b],implicit ws: MustBeString[b])b
scala> coerce(1) // ambiguous<console>:12: error: ambiguous implicit values: both object coerceIntStr in object $iw of type object coerceIntStr and object coerceIntFloat in object $iw of type object coerceIntFloat  match expected type Coerce[Int,b]       coerce(1) // ambiguous             ^
scala> def coerce[a,b](x: a)(implicit ws: MustBeString[b], w: Coerce[a, b]): b = x  coerce: [a,b](x: a)(implicit ws: MustBeString[b],implicit w: Coerce[a,b])b
scala> coerce(1) // okres4: String = 1

now, discuss!
what's the advantage of "chunking" type inference along argument list boundaries?how does this relate to overload resolution?for extra credit: how does this relate to functional dependencies?
--adriaan
ps: thanks to Paul's work on the REPL, you can just copy/paste the above transcript in an interpreter session
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 6 days ago.
Re: Re: Type inference: Scala vs C#
Can I have the REPL read my email and evaluate anything form adriaan [dot] moors [at] epfl [dot] ch?
I agree, this makes a good FAQ.   I also think the arguments for/against per-parameter inference will be interesting.   As such, I'm moving this to scala-debate.

Now:what's the advantage of "chunking" type inference along argument list boundaries?
You can infer upper-bound types across parameters in the parameter list:   def foo[A](x : A, y : A) will infer A as the upper-bound of the two parameters, if it exists.   Otherwise you'd have to write:  def foo[A, B >: A, C >: A](x : B, y : C), which involves two extra types and 16 extra key-presses.  Obviously 16 key-presses is a lot.   In fact, you can type my name in less than 16 key preses, if you don't count middle names.
how does this relate to overload resolution?
overloading is evil.   Avoid it at all costs....  Even so perhaps an example like this can help demonstrate how evil overloading can be (and provide hints as to issues?):
scala> object test{     |   def foo[A](x : A, y : A) = "hai"      |   def foo[A](x : Int, y : A) = "ZOMG"     | } defined module test
// Answers below so you can debate the values of parameter type inference vs. parameter-list type inference scala> test.foo(5, "String")  // Friendly greeting or lolcat freakout?scala> test.foo(5, 5)  // Friendly greeting or lolcat freakout?        scala> test.foo("Hai", 5)  // Friendly greeting or lolcat freakout?






Answers:scala> test.foo(5, "String")  // Friendly greeting or lolcat freakout? res5: java.lang.String = ZOMG
scala> test.foo(5, 5)  // Friendly greeting or lolcat freakout?        res6: java.lang.String = ZOMG
scala> test.foo("Hai", 5)  // Friendly greeting or lolcat freakout? res7: java.lang.String = hai


for extra credit: how does this relate to functional dependencies?
Doesn't a dependency imply you are dysfunctional?


On Wed, Jul 21, 2010 at 10:21 AM, Adriaan Moors <adriaan [dot] moors [at] epfl [dot] ch> wrote:
I don't know if anyone is maintaining a FAQ, but this would certainly make for a good entry.

On Tue, Jul 20, 2010 at 2:46 PM, Dennis Haupt <h-star [at] gmx [dot] de> wrote:
why doesn't scala infer the type here? even java does.
I think it's time for a Scientific Experiment:
adriaan$ scalaWelcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).Type in expressions to have them evaluated.Type :help for more information.
scala> /*     | Scala interpreter experiments to illustrate that type inference & implicit search go from left-to-right,     | with constraints being solved per argument list (once type variable is solved, later argument list has to abide)      | */
scala> def illustrateInfer[a](x: a, y: a) = error("meh") illustrateInfer: [a](x: a,y: a)Nothing
scala> illustrateInfer(1, "a") // well-typed java.lang.RuntimeException: meh at scal...
scala> def illustrateInferCurry[a](x: a)(y: a) = error("meh")  illustrateInferCurry: [a](x: a)(y: a)Nothing
scala> illustrateInferCurry(1)("a") // ill-typed<console>:7: error: type mismatch; found   : java.lang.String("a")  required: Int       illustrateInferCurry(1)("a") // ill-typed                               ^
scala> trait Coerce[A, B] extends (A => B) // typical type class that will lead to ambiguity defined trait Coerce
scala> implicit object coerceIntFloat extends Coerce[Int, Float]{def apply(x: Int) = x.toFloat}defined module coerceIntFloat
scala> implicit object coerceIntStr extends Coerce[Int, String]{def apply(x: Int) = x.toString} defined module coerceIntStr
scala> // first argument list will fix a and b
scala> def coerce2[a,b](x: a, proto: b)(implicit w: Coerce[a, b]): b = x  coerce2: [a,b](x: a,proto: b)(implicit w: Coerce[a,b])b
scala> coerce2(1, "a") // okres2: java.lang.String = 1
scala> trait MustBeString[B]defined trait MustBeString
scala> implicit object beString extends MustBeString[String] defined module beString
scala> def coerce[a,b](x: a)(implicit w: Coerce[a, b], ws: MustBeString[b]): b = xcoerce: [a,b](x: a)(implicit w: Coerce[a,b],implicit ws: MustBeString[b])b
scala> coerce(1) // ambiguous<console>:12: error: ambiguous implicit values: both object coerceIntStr in object $iw of type object coerceIntStr and object coerceIntFloat in object $iw of type object coerceIntFloat  match expected type Coerce[Int,b]       coerce(1) // ambiguous             ^
scala> def coerce[a,b](x: a)(implicit ws: MustBeString[b], w: Coerce[a, b]): b = x  coerce: [a,b](x: a)(implicit ws: MustBeString[b],implicit w: Coerce[a,b])b
scala> coerce(1) // okres4: String = 1

now, discuss!
what's the advantage of "chunking" type inference along argument list boundaries?how does this relate to overload resolution?for extra credit: how does this relate to functional dependencies?
--adriaan
ps: thanks to Paul's work on the REPL, you can just copy/paste the above transcript in an interpreter session

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