[Haskell-beginners] Here's why functions should return functions
Jay Sulzberger
jays at panix.com
Mon Jul 30 21:48:31 CEST 2012
On Mon, 30 Jul 2012, Ertugrul Söylemez <es at ertes.de> wrote:
> Jay Sulzberger <jays at panix.com> wrote:
>
>> There is, in most sub-systems of mathematics, whether like recent type
>> theory or not, a general function, let us call it mcf which in Scheme
>> notation may be defined by executing
>>
>> (define mcf
>> (lambda (a)
>> (lambda (x) a)))
>>
>> Now in Haskell I know that one, perhaps the, parallel definition must
>> result in a polymorphic function.
>
> First let's ensure that we are talking about the same function. I'm
> reading "mcf" as "make constant function". From what I read the Haskell
> equivalent would be this function:
>
> const a _ = a
>
> It may make it not fully polymorphic, but if you don't provide a type
> signature, then the following fully polymorphic type will be inferred:
>
> const :: a -> b -> a
This is good.
>
>
>> What is this definition?
>
> Well, this is the constant function, though with slightly unusual (but
> sensible) semantics for Scheme. Because Scheme syntax requires explicit
> currying the name "make constant function" would also be sensible. It
> is because of the lack of side effects that we call the function simply
> 'const' in Haskell. Otherwise most functions would be prefixed with
> "make".
Ah, yes. Certainly all functions with more than one input.
>
>
>> What implicit constraints are on a?
>
> None.
I am encouraged by this.
>
>
>> Does "lazy vs eager" come in here?
>
> Yes. Even though you have written a curried version of 'const' there,
> Scheme is still a strict language, which means that the result of the
> inner lambda will depend on its argument 'x'. This means:
>
> -- Haskell:
> const a ⥠= a
>
> -- in other words:
> loop = loop -- an infinite loop
> const a loop = a
>
> ; Scheme:
> ((mcf a) â¥) = â¥
>
> (define (loop) (loop)) ; an infinite loop
> ((mcf a) (loop)) = (loop)
Yes, I see, I think.
I think, if we were doing a finer analysis, we might write
((mcf a) (loop)) ~> [(mcf a) waiting] (loop)
where [ waiting] indicates that when loop finishes executing, and
returns, ah, something, perhaps nothing, the constant function
(mcf a) will accept that returned thing. (To be clear: above
line is not Scheme nor indeed is it a phrase of any standard
programming system.)
We here avoid mentioning (\omega + 1) ;)
>
> This is the semantic difference. To relate this to "lazy vs. eager"
> it's important to understand how a nonstrict language like Haskell is
> usually evaluated: Lazy evaluation will defer the evaluation of the
> inner lambda's argument (which is an unnamed '_' here) until it is
> required. Since it is never required it is never evaluated and the
> unevaluated thunk is garbage-collected immediately, unless it is used
> elsewhere.
>
> A strict language like Scheme is usually evaluated eagerly. This means
> that the inner lambda is not entered, until the argument is fully
> evaluated.
Yes.
>
>
>> Are there options to ghc which might modify how Haskell handles the
>> definition?
>
> There are optimization flags, which could change the performance of the
> definition, but a proper Haskell compiler like GHC must ensure that
> semantics are not changed.
>
>
>> Of course, my questions are too many and I hope just for some
>> indications of the first things a beginner should study.
>
> No worries. I'm happy to help. =)
>
>
> Greets,
> Ertugrul
Thanks, Ertugrul!
oo--JS.
More information about the Beginners
mailing list