
On Mon, 30 Jul 2012, Ertugrul Söylemez
Jay Sulzberger
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.