Hi Adrian, | If I have defined a function like this.. | f <args> = <blah> <args> | it could be re-written.. | f = <blah> | | I had always assumed the internal representation of | these 2 definitions would be identical (and should | yield identical code), but it appears that isn't so | (with ghc at least). So.. | | Is there a semantic difference between the two? | Which form is likely to result in faster code?
There are several differences: - The first will not be subject to the monomorphism restriction; the second will require an explicit type signature for f to avoid that fate. - The second will compute a value of <blah> at most once, then cache the result for future use. That could make a program run faster, but if the result of <blah> takes a lot of space, then it could result in a space leak. The first might end up repeating the computation of <blah> each time f is called. For example, compare the evaluation of: let f = (+) (sum [1..1000]) in (f 1, f 2) with: let f x = (+) (sum [1..1000]) x in (f 1, f 2) (Hint: run it in Hugs on a slow computer with :set +s to see the difference, or replace 1000 with a bigger number :-) Denotationally, the two expressions are the same. (In other words, they both produce the same value.) But the example above shows an operational difference in some implementation. (As far as I can tell, however, nothing in the language definition either guarantees or prevents such behavior.) - There could be other differences in generated code and operational behavior, even when <blah> is an expression that cannot be further evaluated without an argument. In Hugs, for example, the definition: f = \x y -> (x,y) will be translated into: f = f' -- note the extra indirection here! f' x y = (x,y) A compiler with more brains, of course, could do better, but the Haskell report doesn't specify which behavior you'll get in general. Personally, I'd tend to let considerations other than performance affect my choice. For example, if I'd declared f :: a -> String -> [(a, String)] then I might use a definition like: f x s = [(x, s)] -- two parameters in the type, so two -- parameters in the definition But if the type signature was f :: a -> Parser a and if I'd defined: type Parser a = String -> [(a, String)] then I'd write the definition of f in the form: f x = \s -> [(x, s)] -- f is a function of one argument -- that returns a parser as a result. Just my 2 cents, however, ... All the best, Mark _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell