1
votes

I am new to Scala and was reading about partially applied functions in Scala. I've a general function "wrap" which can concatenate three strings.

def wrap(prefix: String)(html: String)(suffix: String) = prefix + html + suffix

When I try to make a specialized function like this

val foo = wrap(_)("Hello")(_)

It fails with Missing parameter type error, but works if I provide type for first argument, like this

val foo = wrap(_:String)("Hello")(_)

My questions are:

  1. Why do I have to provide the type redundantly? I had already provided it in general definition of wrap.

  2. Why it doesn't require type for last argument?

2
2) It does require type for last argument too, at least for me. Scala 2.12.7 - ygor
Sometimes the inference engine just needs a hint or two: val semiwrap :String => String => String = wrap(_)("Hello") - jwvh
@ygor . I am also on 2.12.7. It works for me. scala> wrap("fd")("dfd")(_) res0: String => String = $$Lambda$3062/0x0000000800f6b040@27c551c1 - victini

2 Answers

2
votes

As you have discovered, you need to give the compiler a bit more information about the types before it can work out the type of foo. You can either specify the argument types:

val foo = wrap(_: String)("Hello")(_: String)

or the result type

val foo: (String, String) => String = wrap(_)("Hello")(_)

Specifying a single type does not compile in my build using 2.12.7

val foo = wrap(_: String)("Hello")(_) // Does not compile
2
votes

Scala compiler cannot always infer types, for example: think of overloaded methods where it’s impossible for the compiler to know which of them you are referring to.

  def wrap(prefix: String)(html: String)(suffix: String) = prefix + html + suffix
  def wrap(prefix: Int)(html: String)(suffix: String) = prefix.toString + html + suffix

  val foo = wrap(_: String)("Hello")(_: String)
  val foo1 = wrap(_)("Hello")(_)     // compilation Error: Cannot resolve method 'wrap'

So, you need to explicitly specify type parameter like below:

  val foo = wrap(_: String)("Hello")(_: String)
  val foo1 = wrap(_: Int)("Hello")(_: String)

or specify return type explicitly:

  val foo: (String, String) => String = wrap(_)("Hello")(_)
  val foo1: (Int, String) => String = wrap(_)("Hello")(_)