Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell - Lambda calculus equivalent syntax?

While writing some lambda functions in Haskell, I was originally writing the functions like:

tru = \t f -> t
fls = \t f -> f

However, I soon noticed from the examples online that such functions are frequently written like:

tru = \t -> \f -> t
fls = \t -> \f -> f

Specifically, each of the items passed to the function have their own \ and -> as opposed to above. When checking the types of these they appear to be the same. My question is, are they equivalent or do they actually differ in some way? And not only for these two functions, but does it make a difference for functions in general? Thank you much!

like image 774
golmschenk Avatar asked Oct 06 '13 04:10

golmschenk


People also ask

Does Haskell use lambda calculus?

The ghc Haskell compiler operates by (1) desugaring the source program, (2) transforming the program into a version of lambda calculus called System F, and (3) translating the System F to machine language using graph reduction.

What does lambda mean in Haskell?

λ-expressions (λ is the small Greek letter lambda) are a convenient way to easily create anonymous functions — functions that are not named and can therefore not be called out of context — that can be passed as parameters to higher order functions like map, zip etc.

What is lambda abstraction in Haskell?

A lambda abstraction is another name for an anonymous function. It gets its name from the usual notation for writing it: for example, . ( Another common, equivalent notation is: .)


2 Answers

They're the same, Haskell automatically curries things to keep things syntax nice. The following are all equivalent**

foo a b = (a, b)
foo a = \b -> (a, b)
foo = \a b -> (a, b)
foo = \a -> \b -> (a, b)
-- Or we can simply eta convert leaving
foo = (,)

If you want to be idiomatic, prefer either the first or the last. Introducing unnecessary lambdas is good for teaching currying, but in real code just adds syntactic clutter.

However in raw lambda calculus (not Haskell) most manually curry with

\a -> \b -> a b

Because people don't write a lot of lambda calculus by hand and when they do they tend to stick unsugared lambda calculus to keep things simple.

** modulo the monomorphism restriction, which won't impact you anyways with a type signature.

like image 76
Daniel Gratzer Avatar answered Sep 26 '22 17:09

Daniel Gratzer


Though, as jozefg said, they are themselves equivalent, they may lead to different execution behaviour when combined with local variable bindings. Consider

f, f' :: Int -> Int -> Int

with the two definitions

f a x = μ*x
 where μ = sum [1..a]

and

f' a = \x -> μ*x
 where μ = sum [1..a]

These sure look equivalent, and certainly will always yield the same results.

GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help
...
[1 of 1] Compiling Main            ( def0.hs, interpreted )
Ok, modules loaded: Main.
*Main> sum $ map (f 10000) [1..10000]
2500500025000000
*Main> sum $ map (f' 10000) [1..10000]
2500500025000000

However, if you try this yourself, you'll notice that with f takes quite a lot of time whereas with f' you get the result immediately. The reason is that f' is written in a form that prompts GHC to compile it so that actually f' 10000 is evaluated before starting to map it over the list. In that step, the value μ is calculated and stored in the closure of (f' 10000). On the other hand, f is treated simply as "one function of two variables"; (f 10000) is merely stored as a closure containing the parameter 10000 and μ is not calculated at all at first. Only when map applies (f 10000) to each element in the list, the whole sum [1..a] is calculated, which takes some time for each element in [1..10000]. With f', this was not necessary because μ was pre-calculated.

In principle, common-subexpression elimination is an optimisation that GHC is able to do itself, so you might at times get good performance even with a definition like f. But you can't really count on it.

like image 34
leftaroundabout Avatar answered Sep 23 '22 17:09

leftaroundabout