In eager languages like Scheme and Python, you can use a lambda expression without parameters to delay evaluation, e.g. in Scheme (Chicken Scheme):
#;1> (define (make-thunk x) (lambda () (+ x 1)))
#;2> (define t (make-thunk 1))
#;3> (t)
2
In line 2, t
is bound to the unevaluated expression (lambda () (+ 1 1))
, which is then evaluated to 2
in line 3.
Similarly, in Python:
>>> def make_thunk(x): return lambda: x + 1
...
>>> t = make_thunk(1)
>>> t()
2
Using this technique one can implement lazy evaluation in an eager language.
So, I was expecting that Haskell would not have lambda expressions without parameters because the language is already lazy and there is no need to build delayed expressions. To my surprise, I found out that in Haskell it is possible to write the lambda expression
\() -> "s"
which can only be applied to the ()
value like so:
(\() -> "s") ()
giving the result
"s"
Applying this function to any argument other than ()
throws an exception (at least as far as I could see during my tests). This seems different from delayed evaluation in Scheme and Python, because the expression still needs an argument to be evaluated.
So what does a lambda expression without variables (like \() -> "s"
) mean in Haskell and what can it be useful for?
Also, I would be curious to know if similar parameterless lambda expressions exist in (some variety of) lambda-calculus.
Best Answer
Well, the other answers cover what
\() -> "something"
means in Haskell: an unary function that takes()
as argument.What is a function without arguments? – A value. Actually, it can occasionally be useful to think of variables as nullary functions that evaluate to their value. The
let
-syntax for a function without arguments (which doesn't actually exist) ends up giving you a variable binding:let x = 42 in ...
Does lambda calculus have nullary functions? – No. Every function takes exactly one argument. However, this argument may be a list, or the function may return another function that takes the next argument. Haskell prefers the latter solution, so that
a b c
is actually two function calls((a b) c)
. To simulate nullary functions, you have to pass some unused placeholder value.