Dimitris Andreou | 1 Jan 18:06
Picon

Currying

Hi,
I'm new to this list and to Scala too. I'm reading through the currying 
chapter of Programming in Scala, and I've a pretty basic question.

Perhaps I misunderstood the term, but I thought 'currying' described the 
ability to bind some parameters to an existing function and derive 
another one, with fewer parameters. I thought it would be possible to 
take *any* function, treating it as a black-box, bind some parameters to 
it and derive another. But it seems that this can't be applied to a 
function in an after-the-fact fashion - the author must built this 
ability inside a particular function. Also, this doesn't give the 
ability to bind an arbitrary parameter of the function, but the first 
one(s). I.e., if I have a function with four parameters:

f(a, b, c, d)

I could implement it in scala in a way that I could derive functions:

f(b, c, d)
f(c, d)
f(d)
f()

Is there a way I could also derive functions like f(a, b, c), f(a, b, d) 
etc.? But again, I would like to be able to do this opaquely on top of 
any function, not a specially crafted one, or else it doesn't sound too 
useful to me. Can someone try to illuminate me on the subject? If I got 
something entirely wrong, please correct me!

Thanks
(Continue reading)

James Iry | 1 Jan 18:24
Picon
Gravatar

Re: Currying

Currying is taking a function of type (A,B) => C and creating a function of type A => B => C.   In Scala, currying can be done both syntactically (def foo(x:A)(y:B) : C = ...) and using an appropriate function.  For instance, here's a curry function for arity 2

scala> def curry[A,B,C](f : (A,B) => C) = {x : A => y : B => f(x,y)}
curry: [A,B,C]((A, B) => C)(A) => (B) => C

And here's using it

scala> def add(x : Int, y : Int) = x + y
add: (Int,Int)Int

scala> val curriedAdd = curry(add)
curriedAdd: (Int) => (Int) => Int = <function>

scala> val plusOne = curriedAdd(1)
plusOne: (Int) => Int = <function>

scala> plusOne(4)
res0: Int = 5


What you're describing is partial application, which is of course related.  You can use a curry function like above to do partial application by just applying an argument on the same line as where you curry

scala> val plusOne2 = curry(add)(1)
plusOne2: (Int) => Int = <function>

scala> plusOne2(5)
res1: Int = 6

But you don't need all that, because you can partially apply anything in Scala using _ notation

scala> val plusOne3 = add(1, _:Int)
plusOne3: (Int) => Int = <function>

scala> plusOne3(6)
res2: Int = 7

On Thu, Jan 1, 2009 at 9:06 AM, Dimitris Andreou <jim.andreou <at> gmail.com> wrote:
Hi,
I'm new to this list and to Scala too. I'm reading through the currying chapter of Programming in Scala, and I've a pretty basic question.

Perhaps I misunderstood the term, but I thought 'currying' described the ability to bind some parameters to an existing function and derive another one, with fewer parameters. I thought it would be possible to take *any* function, treating it as a black-box, bind some parameters to it and derive another. But it seems that this can't be applied to a function in an after-the-fact fashion - the author must built this ability inside a particular function. Also, this doesn't give the ability to bind an arbitrary parameter of the function, but the first one(s). I.e., if I have a function with four parameters:

f(a, b, c, d)

I could implement it in scala in a way that I could derive functions:

f(b, c, d)
f(c, d)
f(d)
f()

Is there a way I could also derive functions like f(a, b, c), f(a, b, d) etc.? But again, I would like to be able to do this opaquely on top of any function, not a specially crafted one, or else it doesn't sound too useful to me. Can someone try to illuminate me on the subject? If I got something entirely wrong, please correct me!

Thanks
Dimitris Andreou

Dimitris Andreou | 1 Jan 21:15
Picon

Re: Currying

Thanks a lot James! That's a very nice summary, hopefully I'll be able 
to feel at home with all the various forms.

Syntax apart, am I right in thinking that partial appication is a 
superset of currying? Here's my attempt:

scala> def curry[A, B, C](f: (A, B) => C) = (x:A) => f(x, _:B)
curry: [A,B,C]((A, B) => C)(A) => (B) => C

Which seems functionally (no pun) equivalent to the one you gave. I 
understand though that syntactically currying would be better if the 
function has lots of parameters and I wanted to partially apply each 
parameter in the order of appearance (but I can't imagine another 
use-case where the difference of them would be highlighted).

(A side note: the syntax still seems a bit tricky to me. Removing from 
the above the paren's around 'x:A' results in error)

Happy new year! :)
Dimitris

O/H James Iry έγραψε:
> Currying is taking a function of type (A,B) => C and creating a 
> function of type A => B => C.   In Scala, currying can be done both 
> syntactically (def foo(x:A)(y:B) : C = ...) and using an appropriate 
> function.  For instance, here's a curry function for arity 2
>
> scala> def curry[A,B,C](f : (A,B) => C) = {x : A => y : B => f(x,y)}
> curry: [A,B,C]((A, B) => C)(A) => (B) => C
>
> And here's using it
>
> scala> def add(x : Int, y : Int) = x + y
> add: (Int,Int)Int
>
> scala> val curriedAdd = curry(add)
> curriedAdd: (Int) => (Int) => Int = <function>
>
> scala> val plusOne = curriedAdd(1)
> plusOne: (Int) => Int = <function>
>
> scala> plusOne(4)
> res0: Int = 5
>
>
> What you're describing is partial application, which is of course 
> related.  You can use a curry function like above to do partial 
> application by just applying an argument on the same line as where you 
> curry
>
> scala> val plusOne2 = curry(add)(1)
> plusOne2: (Int) => Int = <function>
>
> scala> plusOne2(5)
> res1: Int = 6
>
> But you don't need all that, because you can partially apply anything 
> in Scala using _ notation
>
> scala> val plusOne3 = add(1, _:Int)
> plusOne3: (Int) => Int = <function>
>
> scala> plusOne3(6)
> res2: Int = 7
>
> On Thu, Jan 1, 2009 at 9:06 AM, Dimitris Andreou 
> <jim.andreou <at> gmail.com <mailto:jim.andreou <at> gmail.com>> wrote:
>
>     Hi,
>     I'm new to this list and to Scala too. I'm reading through the
>     currying chapter of Programming in Scala, and I've a pretty basic
>     question.
>
>     Perhaps I misunderstood the term, but I thought 'currying'
>     described the ability to bind some parameters to an existing
>     function and derive another one, with fewer parameters. I thought
>     it would be possible to take *any* function, treating it as a
>     black-box, bind some parameters to it and derive another. But it
>     seems that this can't be applied to a function in an
>     after-the-fact fashion - the author must built this ability inside
>     a particular function. Also, this doesn't give the ability to bind
>     an arbitrary parameter of the function, but the first one(s).
>     I.e., if I have a function with four parameters:
>
>     f(a, b, c, d)
>
>     I could implement it in scala in a way that I could derive functions:
>
>     f(b, c, d)
>     f(c, d)
>     f(d)
>     f()
>
>     Is there a way I could also derive functions like f(a, b, c), f(a,
>     b, d) etc.? But again, I would like to be able to do this opaquely
>     on top of any function, not a specially crafted one, or else it
>     doesn't sound too useful to me. Can someone try to illuminate me
>     on the subject? If I got something entirely wrong, please correct me!
>
>     Thanks
>     Dimitris Andreou
>
>

Paul Chiusano | 1 Jan 22:08
Picon

Re: Currying

Also, fyi, all the Function types have a curry method defined, so given f: (A,B) => C, you can just say f.curry(a), which has the type B => C.

On Thu, Jan 1, 2009 at 3:15 PM, Dimitris Andreou <jim.andreou <at> gmail.com> wrote:
Thanks a lot James! That's a very nice summary, hopefully I'll be able to feel at home with all the various forms.

Syntax apart, am I right in thinking that partial appication is a superset of currying? Here's my attempt:

scala> def curry[A, B, C](f: (A, B) => C) = (x:A) => f(x, _:B)

curry: [A,B,C]((A, B) => C)(A) => (B) => C

Which seems functionally (no pun) equivalent to the one you gave. I understand though that syntactically currying would be better if the function has lots of parameters and I wanted to partially apply each parameter in the order of appearance (but I can't imagine another use-case where the difference of them would be highlighted).

(A side note: the syntax still seems a bit tricky to me. Removing from the above the paren's around 'x:A' results in error)

Happy new year! :)
Dimitris

O/H James Iry έγραψε:
Currying is taking a function of type (A,B) => C and creating a function of type A => B => C.   In Scala, currying can be done both syntactically (def foo(x:A)(y:B) : C = ...) and using an appropriate function.  For instance, here's a curry function for arity 2

scala> def curry[A,B,C](f : (A,B) => C) = {x : A => y : B => f(x,y)}
curry: [A,B,C]((A, B) => C)(A) => (B) => C

And here's using it

scala> def add(x : Int, y : Int) = x + y
add: (Int,Int)Int

scala> val curriedAdd = curry(add)
curriedAdd: (Int) => (Int) => Int = <function>

scala> val plusOne = curriedAdd(1)
plusOne: (Int) => Int = <function>

scala> plusOne(4)
res0: Int = 5


What you're describing is partial application, which is of course related.  You can use a curry function like above to do partial application by just applying an argument on the same line as where you curry

scala> val plusOne2 = curry(add)(1)
plusOne2: (Int) => Int = <function>

scala> plusOne2(5)
res1: Int = 6

But you don't need all that, because you can partially apply anything in Scala using _ notation

scala> val plusOne3 = add(1, _:Int)
plusOne3: (Int) => Int = <function>

scala> plusOne3(6)
res2: Int = 7

On Thu, Jan 1, 2009 at 9:06 AM, Dimitris Andreou <jim.andreou <at> gmail.com <mailto:jim.andreou <at> gmail.com>> wrote:

   Hi,
   I'm new to this list and to Scala too. I'm reading through the
   currying chapter of Programming in Scala, and I've a pretty basic
   question.

   Perhaps I misunderstood the term, but I thought 'currying'
   described the ability to bind some parameters to an existing
   function and derive another one, with fewer parameters. I thought
   it would be possible to take *any* function, treating it as a
   black-box, bind some parameters to it and derive another. But it
   seems that this can't be applied to a function in an
   after-the-fact fashion - the author must built this ability inside
   a particular function. Also, this doesn't give the ability to bind
   an arbitrary parameter of the function, but the first one(s).
   I.e., if I have a function with four parameters:

   f(a, b, c, d)

   I could implement it in scala in a way that I could derive functions:

   f(b, c, d)
   f(c, d)
   f(d)
   f()

   Is there a way I could also derive functions like f(a, b, c), f(a,
   b, d) etc.? But again, I would like to be able to do this opaquely
   on top of any function, not a specially crafted one, or else it
   doesn't sound too useful to me. Can someone try to illuminate me
   on the subject? If I got something entirely wrong, please correct me!

   Thanks
   Dimitris Andreou




Marius Danciu | 2 Jan 19:45
Picon
Gravatar

A bit of help with implicits please ...

Hi,

Here is a program listing:

class Container[T](list: List[T]) {
  def get[U](pos: Int)(implicit c: Convert[T, U]): U = {
    c.cvt(list(pos))
  }
}

trait Convert[T, U] {
  def cvt(t: T): U
}

object Convertors {
    implicit object stringToInt extends Convert[String, Int] {
      def cvt(str: String): Int = java.lang.Integer.parseInt(str)
    }
}


object Main {
  def main(args : Array[String]) : Unit = {
    import Convertors._
    val c = new Container[String]("1" :: "2" :: Nil)
   
    var i: Int = c.get(0) // HERE IT FAILS TO COMPILE
    println(i)
  }
}

So basically we want to convert elements from a List of String (for example) to some other type using of course implicits. The above code fails to compile saying "no implicit argument matching parameter type com.Convert[String,Nothing] was found."

Looks like the type parameter U was inferred with Nothing instead of Int since i variable is of type Int. If I'm adding another argument to get function of type U it works ok. As far as I can see the Int type which would be inferred is not captured anywhere even if the return type is U.

Could you please shed some light?

Br's,
Marius

Erik Engbrecht | 2 Jan 19:59
Picon

Re: A bit of help with implicits please ...

1.  Drop the implicit parameter from Container.get

2.  Make Convertors.stringToInt an implicit def instead of an implicit object

That should accomplish what you want and be simpler to boot.

On Fri, Jan 2, 2009 at 1:45 PM, Marius Danciu <marius.danciu <at> gmail.com> wrote:
Hi,

Here is a program listing:

class Container[T](list: List[T]) {
  def get[U](pos: Int)(implicit c: Convert[T, U]): U = {
    c.cvt(list(pos))
  }
}

trait Convert[T, U] {
  def cvt(t: T): U
}

object Convertors {
    implicit object stringToInt extends Convert[String, Int] {
      def cvt(str: String): Int = java.lang.Integer.parseInt(str)
    }
}


object Main {
  def main(args : Array[String]) : Unit = {
    import Convertors._
    val c = new Container[String]("1" :: "2" :: Nil)
   
    var i: Int = c.get(0) // HERE IT FAILS TO COMPILE
    println(i)
  }
}

So basically we want to convert elements from a List of String (for example) to some other type using of course implicits. The above code fails to compile saying "no implicit argument matching parameter type com.Convert[String,Nothing] was found."

Looks like the type parameter U was inferred with Nothing instead of Int since i variable is of type Int. If I'm adding another argument to get function of type U it works ok. As far as I can see the Int type which would be inferred is not captured anywhere even if the return type is U.

Could you please shed some light?

Br's,
Marius



--
http://erikengbrecht.blogspot.com/
Jim McBeath | 2 Jan 22:20

Re: A bit of help with implicits please ...

>          val c = new Container[String]("1" :: "2" :: Nil)

I believe Scala is not inferring the Int part when instantiating
your Container object because the get(0) is a separate statement from
the creation of the Container object, so it is not using that
information when calculating the type of var c.

If there is some reason you don't want to use Erik's suggestion, your
current approach should work if you add the second type parameter
to your Container class rather than on its get method and specify
that type explicitly when instantiating it:

   class Container[T,U](list: List[T]) {
     def get(pos: Int)(implicit c: Convert[T, U]): U = {
       c.cvt(list(pos))
     }
   }

and

         val c = new Container[String,Int]("1" :: "2" :: Nil)

--
Jim

On Fri, Jan 02, 2009 at 01:59:20PM -0500, Erik Engbrecht wrote:
> Date: Fri, 2 Jan 2009 13:59:20 -0500
> From: Erik Engbrecht <erik.engbrecht <at> gmail.com>
> To: Marius Danciu <marius.danciu <at> gmail.com>
> Cc: Scala list <scala <at> listes.epfl.ch>
> Subject: Re: [scala] A bit of help with implicits please ...
> 
>    1.  Drop the implicit parameter from Container.get
> 
>    2.  Make Convertors.stringToInt an implicit def instead of an implicit
>    object
> 
>    That should accomplish what you want and be simpler to boot.
> 
>    On Fri, Jan 2, 2009 at 1:45 PM, Marius Danciu <marius.danciu <at> gmail.com>
>    wrote:
> 
>      Hi,
>      Here is a program listing:
>      class Container[T](list: List[T]) {
>        def get[U](pos: Int)(implicit c: Convert[T, U]): U = {
>          c.cvt(list(pos))
>        }
>      }
>      trait Convert[T, U] {
>        def cvt(t: T): U
>      }
>      object Convertors {
>          implicit object stringToInt extends Convert[String, Int] {
>            def cvt(str: String): Int = java.lang.Integer.parseInt(str)
>          }
>      }
>      object Main {
>        def main(args : Array[String]) : Unit = {
>          import Convertors._
>          val c = new Container[String]("1" :: "2" :: Nil)
> 
>          var i: Int = c.get(0) // HERE IT FAILS TO COMPILE
>          println(i)
>        }
>      }
>      So basically we want to convert elements from a List of String (for
>      example) to some other type using of course implicits. The above
>      code fails to compile saying "no implicit argument matching
>      parameter type com.Convert[String,Nothing] was found."
>      Looks like the type parameter U was inferred with Nothing instead of
>      Int since i variable is of type Int. If I'm adding another argument
>      to get function of type U it works ok. As far as I can see the Int
>      type which would be inferred is not captured anywhere even if the
>      return type is U.
>      Could you please shed some light?
>      Br's,
>      Marius
> 
>    --
>    http://erikengbrecht.blogspot.com/

Marius Danciu | 2 Jan 23:54
Picon
Gravatar

Re: A bit of help with implicits please ...



On Fri, Jan 2, 2009 at 11:20 PM, Jim McBeath <scala <at> j.jimmc.org> wrote:
>          val c = new Container[String]("1" :: "2" :: Nil)

I believe Scala is not inferring the Int part when instantiating
your Container object because the get(0) is a separate statement from
the creation of the Container object, so it is not using that
information when calculating the type of var c.

Yes I kind of figured that out but why it is inferring Nothing and not Int?
 


If there is some reason you don't want to use Erik's suggestion, your
current approach should work if you add the second type parameter
to your Container class rather than on its get method and specify
that type explicitly when instantiating it:

  class Container[T,U](list: List[T]) {
    def get(pos: Int)(implicit c: Convert[T, U]): U = {
      c.cvt(list(pos))
    }
  }

Yes but if I do that I'm loosing the whole point. I wanted the resulting type to be inferred by compiler and with the help of implicits to have the correct conversion.

It is not that I don't want to use that suggestion (btw thank you Erik!), I'm quite aware of it but still I'd like to know what is really wrong with the original code.

Of course this would work:

class Container[T](list: List[T]) {
 
  def get[U](pos: Int)(implicit c: T => U): U = {
    c(list(pos))
  }
}

object Main {

  implicit def stringToInt(str: String) : Int = java.lang.Integer.parseInt(str)

  def main(args : Array[String]) : Unit = {

    val c = new Container[String]("1" :: "2" :: Nil)
   
    var i: Int = c.get(0)
    println(i)
  }
}



FWIW that this is not a "real life" case but rather an example so I would like to understand why Nothing is inferred instead on Int ... and my assumption right now is that because there is no parameter of type U for get(...) function ... as if I add one it works fine but the function signature is loosing its sense.



and

        val c = new Container[String,Int]("1" :: "2" :: Nil)

--
Jim

On Fri, Jan 02, 2009 at 01:59:20PM -0500, Erik Engbrecht wrote:
> Date: Fri, 2 Jan 2009 13:59:20 -0500
> From: Erik Engbrecht <erik.engbrecht <at> gmail.com>
> To: Marius Danciu <marius.danciu <at> gmail.com>
> Cc: Scala list <scala <at> listes.epfl.ch>
> Subject: Re: [scala] A bit of help with implicits please ...
>
>    1.  Drop the implicit parameter from Container.get
>
>    2.  Make Convertors.stringToInt an implicit def instead of an implicit
>    object
>
>    That should accomplish what you want and be simpler to boot.
>
>    On Fri, Jan 2, 2009 at 1:45 PM, Marius Danciu <marius.danciu <at> gmail.com>
>    wrote:
>
>      Hi,
>      Here is a program listing:
>      class Container[T](list: List[T]) {
>        def get[U](pos: Int)(implicit c: Convert[T, U]): U = {
>          c.cvt(list(pos))
>        }
>      }
>      trait Convert[T, U] {
>        def cvt(t: T): U
>      }
>      object Convertors {
>          implicit object stringToInt extends Convert[String, Int] {
>            def cvt(str: String): Int = java.lang.Integer.parseInt(str)
>          }
>      }
>      object Main {
>        def main(args : Array[String]) : Unit = {
>          import Convertors._
>          val c = new Container[String]("1" :: "2" :: Nil)
>
>          var i: Int = c.get(0) // HERE IT FAILS TO COMPILE
>          println(i)
>        }
>      }
>      So basically we want to convert elements from a List of String (for
>      example) to some other type using of course implicits. The above
>      code fails to compile saying "no implicit argument matching
>      parameter type com.Convert[String,Nothing] was found."
>      Looks like the type parameter U was inferred with Nothing instead of
>      Int since i variable is of type Int. If I'm adding another argument
>      to get function of type U it works ok. As far as I can see the Int
>      type which would be inferred is not captured anywhere even if the
>      return type is U.
>      Could you please shed some light?
>      Br's,
>      Marius
>
>    --
>    http://erikengbrecht.blogspot.com/

Jim McBeath | 3 Jan 20:06

Re: A bit of help with implicits please ...

On Sat, Jan 03, 2009 at 12:54:36AM +0200, Marius Danciu wrote:
>    On Fri, Jan 2, 2009 at 11:20 PM, Jim McBeath <scala <at> j.jimmc.org> wrote:
> 
>    >          val c = new Container[String]("1" :: "2" :: Nil)
> 
>      I believe Scala is not inferring the Int part when instantiating
>      your Container object because the get(0) is a separate statement
>      from
>      the creation of the Container object, so it is not using that
>      information when calculating the type of var c.
> 
>    Yes I kind of figured that out but why it is inferring Nothing and not
>    Int?

Ah, I see what you are saying:  It works if you use this line:

    val i = c.get[Int](0)

so why can't it infer Int instead of Nothing on that line when
no explicit type is given?  I don't know the answer to that.

By the way, Scala will infer the "String" type for T in your example,
so you can skip the [String] and write

    val c = new Container("1" :: "2" :: Nil)

>      If there is some reason you don't want to use Erik's suggestion,
>      your
>      current approach should work if you add the second type parameter
>      to your Container class rather than on its get method and specify
>      that type explicitly when instantiating it:
>        class Container[T,U](list: List[T]) {
>          def get(pos: Int)(implicit c: Convert[T, U]): U = {
>            c.cvt(list(pos))
>          }
>        }
> 
>    Yes but if I do that I'm loosing the whole point. I wanted the
>    resulting type to be inferred by compiler and with the help of
>    implicits to have the correct conversion.

Scala does not do Hindley-Milner global type inference as does
Haskell.  Sometimes it needs a bit of assistance to figure out
things that are obvious to us humans.

--
Jim

Marius Danciu | 3 Jan 20:17
Picon
Gravatar

Re: A bit of help with implicits please ...



On Sat, Jan 3, 2009 at 9:06 PM, Jim McBeath <scala <at> j.jimmc.org> wrote:
On Sat, Jan 03, 2009 at 12:54:36AM +0200, Marius Danciu wrote:
>    On Fri, Jan 2, 2009 at 11:20 PM, Jim McBeath <scala <at> j.jimmc.org> wrote:
>
>    >          val c = new Container[String]("1" :: "2" :: Nil)
>
>      I believe Scala is not inferring the Int part when instantiating
>      your Container object because the get(0) is a separate statement
>      from
>      the creation of the Container object, so it is not using that
>      information when calculating the type of var c.
>
>    Yes I kind of figured that out but why it is inferring Nothing and not
>    Int?

Ah, I see what you are saying:  It works if you use this line:

   val i = c.get[Int](0)

Right .. although I expected the same thing with var i: Int = c.get(0) since compiler knows the type of i.
 


so why can't it infer Int instead of Nothing on that line when
no explicit type is given?  I don't know the answer to that.

By the way, Scala will infer the "String" type for T in your example,
so you can skip the [String] and write

   val c = new Container("1" :: "2" :: Nil)

Yup I know that.
 


>      If there is some reason you don't want to use Erik's suggestion,
>      your
>      current approach should work if you add the second type parameter
>      to your Container class rather than on its get method and specify
>      that type explicitly when instantiating it:
>        class Container[T,U](list: List[T]) {
>          def get(pos: Int)(implicit c: Convert[T, U]): U = {
>            c.cvt(list(pos))
>          }
>        }
>
>    Yes but if I do that I'm loosing the whole point. I wanted the
>    resulting type to be inferred by compiler and with the help of
>    implicits to have the correct conversion.

Scala does not do Hindley-Milner global type inference as does
Haskell.  Sometimes it needs a bit of assistance to figure out
things that are obvious to us humans.

Right ... Many thanks Jim !
 


--
Jim


Gmane