
Hi, Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell? Thanks!

Hi
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)?
No. See http://haskell.org/haskellwiki/Currying
Am I getting partial evaluation for free just by using Haskell?
No. You can arrange certain things so you get some benefits, but thats a more advanced topic. Thanks Neil

Fernando Rodriguez
Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell?
No, currying is this: Prelude> let f x y = 1 + x * ( y - 3 ) Prelude> let g = f 1 Prelude> let h = f 2 Prelude> g 1 -1 Prelude> g 2 0 Prelude> h 1 -3 Prelude> h 2 -1 or, a bit more confusing and possibly enlightening, Prelude> let y f = f $ y f Prelude> :t y y :: (b -> b) -> b Prelude> let fixpoint f n = if n <= 1 then 1 else n * (f $ n - 1) Prelude> :t fixpoint fixpoint :: (Num b, Ord b) => (b -> b) -> b -> b Prelude> let fac = y fixpoint Prelude> :t fac fac :: Integer -> Integer Prelude> fac 10 3628800 Prelude> fac 100 9332621544394415268169923885626670049071596826438162146859296389521759999 3229915608941463976156518286253697920827223758251185210916864000000000000 000000000000 Note that "fixpoint 3" won't work, and that's good. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On Wed, 2008-01-09 at 00:51 +0100, Achim Schneider wrote:
Fernando Rodriguez
wrote: Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell?
No, currying is this:
No, it is not. This is partial application. See the wiki page Neil referenced.
Prelude> let f x y = 1 + x * ( y - 3 ) Prelude> let g = f 1 Prelude> let h = f 2 Prelude> g 1 -1 Prelude> g 2 0 Prelude> h 1 -3 Prelude> h 2 -1
or, a bit more confusing and possibly enlightening,
Prelude> let y f = f $ y f Prelude> :t y y :: (b -> b) -> b Prelude> let fixpoint f n = if n <= 1 then 1 else n * (f $ n - 1) Prelude> :t fixpoint fixpoint :: (Num b, Ord b) => (b -> b) -> b -> b Prelude> let fac = y fixpoint Prelude> :t fac fac :: Integer -> Integer Prelude> fac 10 3628800
Prelude> fac 100 9332621544394415268169923885626670049071596826438162146859296389521759999 3229915608941463976156518286253697920827223758251185210916864000000000000 000000000000
Note that "fixpoint 3" won't work, and that's good.

Derek Elkins
On Wed, 2008-01-09 at 00:51 +0100, Achim Schneider wrote:
Fernando Rodriguez
wrote: Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell?
No, currying is this:
No, it is not. This is partial application. See the wiki page Neil referenced.
Which works because of the functions being curried... of course, the usage is to "partly" apply a function, which is not possible, as all Haskell functions are, by default, curried, and thus only have one parameter, which can either be applied or not. Partial evaluation, OTOH, goes into the direction of laziness vs. eagerness: Iff the compiler sees that a thunk is only dependent on data known at compile-time, it may choose to evaluate this thunk already at compile-time, if you're lucky and the compiler isn't lazy, main = putStrLn $ show $ 1 + 2 might end up being main = putStrLn "3" in the object file. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On Wed, 2008-01-09 at 03:37 +0100, Achim Schneider wrote:
Derek Elkins
wrote: On Wed, 2008-01-09 at 00:51 +0100, Achim Schneider wrote:
Fernando Rodriguez
wrote: Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell?
No, currying is this:
No, it is not. This is partial application. See the wiki page Neil referenced.
Which works because of the functions being curried...
and therefore partial application can't be currying. Currying is the operation of turning (a,b) -> c into a -> b -> c. Nothing more.
of course, the usage is to "partly" apply a function, which is not possible, as all Haskell functions are, by default, curried, and thus only have one parameter, which can either be applied or not.
Indeed. Partial application is a fuzzy term. I give a potential objective definition here: http://lambda-the-ultimate.org/node/2266#comment-33620
Partial evaluation, OTOH, goes into the direction of laziness vs. eagerness: Iff the compiler sees that a thunk is only dependent on data known at compile-time, it may choose to evaluate this thunk already at compile-time, if you're lucky and the compiler isn't lazy,
Partial evaluation has little to do with lazy v. eager evaluation.
main = putStrLn $ show $ 1 + 2
might end up being
main = putStrLn "3"
in the object file.

Derek Elkins
On Wed, 2008-01-09 at 03:37 +0100, Achim Schneider wrote:
Derek Elkins
wrote: On Wed, 2008-01-09 at 00:51 +0100, Achim Schneider wrote:
Fernando Rodriguez
wrote: Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell?
No, currying is this:
No, it is not. This is partial application. See the wiki page Neil referenced.
Which works because of the functions being curried...
and therefore partial application can't be currying. Currying is the operation of turning (a,b) -> c into a -> b -> c. Nothing more.
of course, the usage is to "partly" apply a function, which is not possible, as all Haskell functions are, by default, curried, and thus only have one parameter, which can either be applied or not.
Indeed. Partial application is a fuzzy term. I give a potential objective definition here: http://lambda-the-ultimate.org/node/2266#comment-33620
Yes, it seems kind of obvious that eating a chicken isn't the same as currying a chicken, but then there's a difference between eating a grilled and a curried chicken... and cooking is always more complex than eating. And you just can't have a curried chicken when there's no one around that curries them. So, currying can also be the operation of turning (define (foo x y) (+ x y)) into foo x y = x + y or, mere syntactically, foo x y = x + y into foo = \x -> \y -> x + y
Partial evaluation, OTOH, goes into the direction of laziness vs. eagerness: Iff the compiler sees that a thunk is only dependent on data known at compile-time, it may choose to evaluate this thunk already at compile-time, if you're lucky and the compiler isn't lazy,
Partial evaluation has little to do with lazy v. eager evaluation.
Well, enough for a thunk to be a reasonable metaphor for a candidate partial evaluation. The compiler is eager, so that the result is memoized before it is used... or not, but then that may not be deducible for the compiler. It's a bit like stop and go traffic. "Opportunistic evaluation" probably fits the concept better than "eager". Can we stop nit-picking, please? -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On Wed, 2008-01-09 at 04:32 +0100, Achim Schneider wrote:
Derek Elkins
wrote: On Wed, 2008-01-09 at 03:37 +0100, Achim Schneider wrote:
Derek Elkins
wrote: On Wed, 2008-01-09 at 00:51 +0100, Achim Schneider wrote:
Fernando Rodriguez
wrote: Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell?
No, currying is this:
No, it is not. This is partial application. See the wiki page Neil referenced.
Which works because of the functions being curried...
and therefore partial application can't be currying. Currying is the operation of turning (a,b) -> c into a -> b -> c. Nothing more.
of course, the usage is to "partly" apply a function, which is not possible, as all Haskell functions are, by default, curried, and thus only have one parameter, which can either be applied or not.
Indeed. Partial application is a fuzzy term. I give a potential objective definition here: http://lambda-the-ultimate.org/node/2266#comment-33620
Yes, it seems kind of obvious that eating a chicken isn't the same as currying a chicken, but then there's a difference between eating a grilled and a curried chicken... and cooking is always more complex than eating. And you just can't have a curried chicken when there's no one around that curries them.
So, currying can also be the operation of turning
(define (foo x y) (+ x y))
into
foo x y = x + y
or, mere syntactically,
foo x y = x + y
into
foo = \x -> \y -> x + y
Partial evaluation, OTOH, goes into the direction of laziness vs. eagerness: Iff the compiler sees that a thunk is only dependent on data known at compile-time, it may choose to evaluate this thunk already at compile-time, if you're lucky and the compiler isn't lazy,
Partial evaluation has little to do with lazy v. eager evaluation.
Well, enough for a thunk to be a reasonable metaphor for a candidate partial evaluation. The compiler is eager, so that the result is memoized before it is used... or not, but then that may not be deducible for the compiler. It's a bit like stop and go traffic. "Opportunistic evaluation" probably fits the concept better than "eager".
Can we stop nit-picking, please?
Can we stop using confusing, misleading or outright wrong definitions and analogies? This is how we end up with people thinking 'currying' = 'partial application' = 'partial evaluation' or 'laziness' = 'memoization' or 'monads' = 'state passing' = 'continuations' or 'type classes' = 'OO classes'

On 8 Jan 2008, at 9:01 PM, Derek Elkins wrote:
On Tue, 2008-01-08 at 21:44 -0800, Jonathan Cast wrote:
On 8 Jan 2008, at 7:56 PM, Derek Elkins wrote:
Can we stop using confusing, misleading or outright wrong definitions and analogies?
What, and bring CS to a halt?
CS wouldn't be the only thing brought to a halt...
Good point. We're really discussing what, the end of humanity as we know it? jcc

Derek Elkins
Can we stop using confusing, misleading or outright wrong definitions and analogies?
No, we can't, ever, that's plain impossible. And will never stop to use enlightening, inspiring or vastly approximate or aggregate definitions and analogies, and I won't stop laughing about my mistakes. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

Achim Schneider
Prelude> let y f = f $ y f Prelude> :t y y :: (b -> b) -> b
Just out of curiosity: Where the heck does 'a' hide? -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On Tue, 08 Jan 2008 18:59:22 -0500, Achim Schneider
Achim Schneider
wrote: Prelude> let y f = f $ y f Prelude> :t y y :: (b -> b) -> b
Just out of curiosity: Where the heck does 'a' hide?
Beg pardon? Are you referring to the type of y being described with 'b' instead of 'a'? Cheers, Brad Larsen

"Brad Larsen"
On Tue, 08 Jan 2008 18:59:22 -0500, Achim Schneider
wrote: Achim Schneider
wrote: Prelude> let y f = f $ y f Prelude> :t y y :: (b -> b) -> b
Just out of curiosity: Where the heck does 'a' hide?
Beg pardon? Are you referring to the type of y being described with 'b' instead of 'a'?
Yes. -- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On Jan 9, 2008 1:07 AM, Achim Schneider
Beg pardon? Are you referring to the type of y being described with 'b' instead of 'a'?
Yes.
"(a -> a) -> a" and "(b -> b) -> b" are equivalent. For some reason ghc uses b instead of a if you are picky about it, just provide a type signature explicitly. Prelude> let {y :: (a -> a) -> a ; y f = f $ y f} Prelude> :t y y :: (a -> a) -> a

"Alfonso Acosta"
On Jan 9, 2008 1:07 AM, Achim Schneider
wrote: Beg pardon? Are you referring to the type of y being described with 'b' instead of 'a'?
Yes.
"(a -> a) -> a" and "(b -> b) -> b" are equivalent.
For some reason ^^^^^^^^^^^^^^^
Yes, exactly that wire which isn't obscured by the boiler plate has kindled my interest.
ghc uses b instead of a if you are picky about it, just provide a type signature explicitly.
Prelude> let {y :: (a -> a) -> a ; y f = f $ y f} Prelude> :t y y :: (a -> a) -> a
-- (c) this sig last receiving data processing entity. Inspect headers for past copyright information. All rights reserved. Unauthorised copying, hiring, renting, public performance and/or broadcasting of this signature prohibited.

On Jan 9, 2008 12:39 AM, Achim Schneider
Yes, exactly that wire which isn't obscured by the boiler plate has kindled my interest.
The name of a type variable doesn't really matter. GHC tries to preserve the names you give, otherwise it creates their own. For example, Prelude> :t \a b c d e f g -> (a,b,c,d,e,f,g) \a b c d e f g -> (a,b,c,d,e,f,g) :: t -> t1 -> t2 -> t3 -> t4 -> t5 -> t6 -> (t, t1, t2, t3, t4, t5, t6) Welll, so why 'b'? Well, GHC didn't choose 'b' at all =) Prelude> :t let y f = f (y f) in y let y f = f (y f) in y :: (t -> t) -> t but Prelude> :t let y f = f $ y f in y let y f = f $ y f in y :: (b -> b) -> b because Prelude> :t ($) ($) :: (a -> b) -> a -> b In another exemple, Prelude> :t \a b c d e f g -> (id a,b,c,d,e,f,g) \a b c d e f g -> (id a,b,c,d,e,f,g) :: a -> t -> t1 -> t2 -> t3 -> t4 -> t5 -> (a, t, t1, t2, t3, t4, t5) Prelude> :t \a b c d e f g -> (a,b,c,d,id e,f,g) \a b c d e f g -> (a,b,c,d,id e,f,g) :: t -> t1 -> t2 -> t3 -> a -> t4 -> t5 -> (t, t1, t2, t3, a, t4, t5) Prelude> :t \a b c d e f g -> (a,b,id c,d,id e,f,g) \a b c d e f g -> (a,b,id c,d,id e,f,g) :: t -> t1 -> a -> t2 -> a1 -> t3 -> t4 -> (t, t1, a, t2, a1, t3, t4) -- Felipe.

Fernando Rodriguez wrote:
Hi,
Is currying in Haskell the same thing as Partial Evaluation (http://en.wikipedia.org/wiki/Partial_evaluation)? Am I getting partial evaluation for free just by using Haskell? Thanks!
I'm not sure you got a straight answer, although you provoked some discussion. Currying is the transformation which takes a function which takes multiple parameters "all at once", into a function which takes one parameter, returning a function which takes one more parameter, returning.... I.e.: uncurried function: f :: (a,b,c,d) -> e takes four parameters "all at once". In haskell it has to take them as a tuple. The corresponding curried function: f :: a -> b -> c -> d -> e Takes one parameter (of type a), and returns a function of type (b -> c -> d ->e). This takes one parameter of type b, and returns a function of type (c -> d -> e). This takes one parameter of type c and returns a function of type (d -> e). This takes one parameter of type d and returns a result of type e. So, in the end, both forms of f take four parameters and give a result of type e. The difference is that the curried form takes them "one at a time", and you can "stop partway" with only some of the parameters supplied. This process of "stopping partway" is called "partial application" (not partial evaluation), and it's a useful technique when working with higher-order functions. Convention in haskell, ML, and similar languages is to use the curried style predominantly. This is for a variety of reasons; the most practically oriented reason is simply that it makes partial application straightforward, which is a useful technique. Now for the second half of your question! Partial Evaluation is cool, but nobody has worked out a good way to get it for free. Some compilers do some kinds of partial evaluation. The "constant folding" that most C compilers do is a very simple case of partial evaluation. In principle, languages like haskell give the compiler a lot more information to determine how much partial evaluation is feasible (especially that the compiler knows which functions are pure). It remains an interesting engineering problem working out which bits to do, though. GHC does not do very much partial evaluation, although some of its optimisations (SpecConstr and some RULES pragmas) are partial-evaluation in a sense. Neil Mitchell's interesting (but as far as I know, work-in-progress) Supero project, http://www-users.cs.york.ac.uk/~ndm/supero/ , is a closely related notion of compilation. Jules
participants (9)
-
Achim Schneider
-
Alfonso Acosta
-
Brad Larsen
-
Derek Elkins
-
Felipe Lessa
-
Fernando Rodriguez
-
Jonathan Cast
-
Jules Bean
-
Neil Mitchell