Re: [Haskell-cafe] Laziness question
Nicolas, Luke, SH More importantly, the type-class approach is flawed [...]. It assumes SH that all seq-related constraints can be read off from type variables, SH which is in fact not the case. LP Could you provide an example (or a specific example or explanation in LP the paper) of what you mean by this? I don't remember the exact details, but if I remember correctly the main concern of the authors is that by requiring that all function types are in Eval as well, as an older version of the Report did, applications of seq to values of function type are not reflected in types and hence, types do not convey enough information to state some necessary seq-induced extra conditions for parametricity results. Anyway, I guess Janis and Daniel will do a far better job commenting at this. As an aside, or a shameless plug if you will, in a paper presented at this year's PEPM [*], Jurriaan and I mention that having information about uses of seq explicitly available, particularly in types, could be favourable for strictness analysis as well. NP Actually my point is that if we do not use any polymorphic primitive to NP implement a family of seq functions then it cannot be flawed. Indeed NP if you read type classes as a way to implicitly pass and pick functions NP then it cannot add troubles. NP Finally maybe we can simply forbidden the forcing of function (as we do NP with Eq). The few cases where it does matter will rescue to NP unsafeSeqFunction. I guess not having functions types in Eval would indeed make parametricity less of an issue, but I do not quite agree that the cases in which one may need seq on values of function type are insignificant. Cheers, Stefan [*] Stefan Holdermans and Jurriaan Hage. Making “stricterness” more relevant. In John P. Gallagher and Janis Voigtländer, editors, Proceedings of the 2010 ACM SIGPLAN Workshop on Partial Evaluation and Program Manipulation, PEPM 2010, Madrid, Spain, January 18–19, 2010, pages 121–130. ACM Press, 2010. http://people.cs.uu.nl/stefan/pubs/holdermans10making.html___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
Brandon S Allbery KF8NH allb...@ece.cmu.edu writes: Exactly. (I was being cagey because the first response was cagey, possibly suspecting a homework question although it seems like an odd time for it.) Why is it an odd time for it? Here in Australia (and presumably other countries in the southern hemisphere) this week will be the second or third week of semester... -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sat, 31 Jul 2010 17:30:54 -0400, Brandon S Allbery KF8NH allb...@ece.cmu.edu wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 7/31/10 16:58 , wren ng thornton wrote: Brandon S Allbery KF8NH wrote: michael rice wrote: Are you saying: [ head x ] - [ *thunk* ] and length [ *thunk* ] - 1, independent of what *thunk* is, even head [], i.e., *thunk* never needs be evaluated? Exactly. (I was being cagey because the first response was cagey, possibly suspecting a homework question although it seems like an odd time for it.) length not only does not look inside of the thunk, it *can't* look inside it; all it knows is that it has a list, it specifically does *not* know what that list can hold. So the only thing it can do is count the number of unknown somethings in the list. Not entirely true: stupidlyStrictLength :: [a] - Integer stupidlyStrictLength [] = 0 stupidlyStrictLength (x:xs) = x `seq` 1 + stupidlyStrictLength xs Given all the messes seq makes (hey, go behind the compiler's back and touch this arbitrary value of arbitrary type), I generally consider it to be unsafeSeq :) I would deeply in favor of renaming seq to unsafeSeq, and introduce a type class to reintroduce seq in a disciplined way. -- Nicolas Pouillard http://nicolaspouillard.fr ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
Nicolas, I would deeply in favor of renaming seq to unsafeSeq, and introduce a type class to reintroduce seq in a disciplined way. There is a well-documented [1] trade-off here: Often, calls to seq are introduced late in a developing cycle; typically after you have discovered a space leak and figured out how to resolve it. Then you introduce a call to seq somewhere deep in a call chain. If seq were a class method, you would know have to work your way upward in the call chain to update all type signatures you had written there. Clearly, this is quite tedious. And then, almost just as often, you find out that actually you did not quite figure out how to resolve the space leak, because it's still there. So, you remove your freshly introduced call to seq and, indeed, work your way to the call chain again to remove all now superfluous class constraints from the type signatures. (By the way, this is typically the sort of task, IDEs with refactoring support excel at, but these are unfortunately not ubiquitous for Haskell yet.) More importantly, the type-class approach is flawed [2]. It assumes that all seq-related constraints can be read off from type variables, which is in fact not the case. Cheers, Stefan [1] Paul Hudak, John Hughes, Simon Peyton Jones, and Philip Wadler. A history of Haskell: Being lazy with class. In Barbara G. Ryder and Brent Hailpern, editors, Proceedings of the Third ACM SIGPLAN History of Programming Languages Conference (HOPL-III), San Diego, California, USA, 9–10 June 2007, pages 1–55. ACM Press, 2007. http://doi.acm.org/10.1145/1238844.1238856 [2] Daniel Seidel and Janis Voigtländer. Taming selective strictness. In Stefan Fischer, Erik Maehle, and Rüdiger Reischuk, editors, INFORMATIK 2009 – Im Focus das Leben, Beiträge der 39. Jahrestagung der Gesellschaft für Informatik e.V. (GI), 28. September – 2. Oktober, in Lübeck, volume 154 of Lecture Notes in Informatics, pages 2916–2930. GI, 2009.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sun, Aug 1, 2010 at 2:53 AM, Stefan Holdermans ste...@vectorfabrics.com wrote: Nicolas, I would deeply in favor of renaming seq to unsafeSeq, and introduce a type class to reintroduce seq in a disciplined way. There is a well-documented [1] trade-off here: Often, calls to seq are introduced late in a developing cycle; typically after you have discovered a space leak and figured out how to resolve it. Then you introduce a call to seq somewhere deep in a call chain. If seq were a class method, you would know have to work your way upward in the call chain to update all type signatures you had written there. Clearly, this is quite tedious. And then, almost just as often, you find out that actually you did not quite figure out how to resolve the space leak, because it's still there. So, you remove your freshly introduced call to seq and, indeed, work your way to the call chain again to remove all now superfluous class constraints from the type signatures. (By the way, this is typically the sort of task, IDEs with refactoring support excel at, but these are unfortunately not ubiquitous for Haskell yet.) That's a reasonable concern. I suppose that would be the reason for keeping unsafeSeq around if we do typeclassify seq. More importantly, the type-class approach is flawed [2]. It assumes that all seq-related constraints can be read off from type variables, which is in fact not the case. Could you provide an example (or a specific example or explanation in the paper) of what you mean by this? Luke Cheers, Stefan [1] Paul Hudak, John Hughes, Simon Peyton Jones, and Philip Wadler. A history of Haskell: Being lazy with class. In Barbara G. Ryder and Brent Hailpern, editors, Proceedings of the Third ACM SIGPLAN History of Programming Languages Conference (HOPL-III), San Diego, California, USA, 9–10 June 2007, pages 1–55. ACM Press, 2007. http://doi.acm.org/10.1145/1238844.1238856 [2] Daniel Seidel and Janis Voigtländer. Taming selective strictness. In Stefan Fischer, Erik Maehle, and Rüdiger Reischuk, editors, INFORMATIK 2009 – Im Focus das Leben, Beiträge der 39. Jahrestagung der Gesellschaft für Informatik e.V. (GI), 28. September – 2. Oktober, in Lübeck, volume 154 of Lecture Notes in Informatics, pages 2916–2930. GI, 2009.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sun, 1 Aug 2010 10:53:24 +0200, Stefan Holdermans ste...@vectorfabrics.com wrote: Nicolas, I would deeply in favor of renaming seq to unsafeSeq, and introduce a type class to reintroduce seq in a disciplined way. There is a well-documented [1] trade-off here: Often, calls to seq are introduced late in a developing cycle; typically after you have discovered a space leak and figured out how to resolve it. Then you introduce a call to seq somewhere deep in a call chain. If seq were a class method, you would know have to work your way upward in the call chain to update all type signatures you had written there. Clearly, this is quite tedious. And then, almost just as often, you find out that actually you did not quite figure out how to resolve the space leak, because it's still there. So, you remove your freshly introduced call to seq and, indeed, work your way to the call chain again to remove all now superfluous class constraints from the type signatures. (By the way, this is typically the sort of task, IDEs with refactoring support excel at, but these are unfortunately not ubiquitous for Haskell yet.) Only in the case where the type of the value being forced is not known, otherwise the class constraint get silently discarded. More importantly, the type-class approach is flawed [2]. It assumes that all seq-related constraints can be read off from type variables, which is in fact not the case. Indeed they give some account to the type class approach but not enough IMHO. Sure forcing functions is a tricky business and having a generic instance for functions is clearly not the solution (as they explain it with foldl vs foldl'''). However I absolutely do not buy their argument using as example a function f :: Eval (a - Int) = (a - Int) - (a - Int) - Int. They consider as an issue the fact that the type does not tell us on which argument seq is used. I think it is fine we may want a more precise type for it to get more properties out of it but it is not flawed. As much as we don't know where (==) is used given a function of type ∀ a. Eq a = [a] - [a]. Actually my point is that if we do not use any polymorphic primitive to implement a family of seq functions then it cannot be flawed. Indeed if you read type classes as a way to implicitly pass and pick functions then it cannot add troubles. Finally maybe we can simply forbidden the forcing of function (as we do with Eq). The few cases where it does matter will rescue to unsafeSeqFunction. Cheers, -- Nicolas Pouillard http://nicolaspouillard.fr ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sun, Aug 1, 2010 at 11:29 AM, Nicolas Pouillard nicolas.pouill...@gmail.com wrote: Finally maybe we can simply forbidden the forcing of function (as we do with Eq). The few cases where it does matter will rescue to unsafeSeqFunction. What's the problem with class Eval a where seq :: a - t - t instance Eval b = Eval (a - b) where seq f = seq (f undefined) It would reduce at least to WHNF as unsafeSeq would. Does it compute more than WHNF? Hmmm, I see, if we had f :: Int - Int f _ = undefined Then my seq above would diverge while unsafeSeq wouldn't. Perhaps that instance would be a good compromise if we insist in not using 'unsafeSeq' to define it. Cheers, =) -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sunday 01 August 2010 10:52:48 am Felipe Lessa wrote: On Sun, Aug 1, 2010 at 11:29 AM, Nicolas Pouillard nicolas.pouill...@gmail.com wrote: Finally maybe we can simply forbidden the forcing of function (as we do with Eq). The few cases where it does matter will rescue to unsafeSeqFunction. What's the problem with class Eval a where seq :: a - t - t instance Eval b = Eval (a - b) where seq f = seq (f undefined) It would reduce at least to WHNF as unsafeSeq would. Does it compute more than WHNF? Hmmm, I see, if we had f :: Int - Int f _ = undefined Then my seq above would diverge while unsafeSeq wouldn't. Perhaps that instance would be a good compromise if we insist in not using 'unsafeSeq' to define it. It also diverges for every strict function f. seq id x = seq (id undefined) x = seq undefined x = undefined -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
michael rice schrieb: So, g is stricter than f? Wouldn't both functions need to evaluate x to the same level, *thunk* : *thunk* to insure listhood? No. :-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sat, Jul 31, 2010 at 4:56 PM, michael rice nowg...@yahoo.com wrote: From: http://en.wikibooks.org/wiki/Haskell/Laziness Given two functions of one parameter, f and g, we say f is stricter than g if f x evaluates x to a deeper level than g x Exercises 1. Which is the stricter function? f x = length [head x] g x = length (tail x) Prelude let f x = length [head x] Prelude let g x = length (tail x) Prelude f undefined 1 Prelude g undefined *** Exception: Prelude.undefined Prelude So, g is stricter than f? Wouldn't both functions need to evaluate x to the same level, *thunk* : *thunk* to insure listhood? f x = length [head *thunk* : *thunk*] g x = length (tail *thunk* : *thunk*) Michael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe Notice the two different kinds of brackets being used in f versus g :) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
OK, in f, *length* already knows it's argument is a list. In g, *length* doesn't know what's inside the parens, extra evaluation there. So g is already ahead before we get to what's inside the [] and (). But since both still have eval x to *thunk* : *thunk*, g evaluates to a deeper level? Michael Wouldn't both functions need to evaluate x to the same level, *thunk* : *thunk* to insure listhood? f x = length [head *thunk* : *thunk*] g x = length (tail *thunk* : *thunk*) Michael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe Notice the two different kinds of brackets being used in f versus g :) --- On Sat, 7/31/10, Ben Millwood hask...@benmachine.co.uk wrote: From: Ben Millwood hask...@benmachine.co.uk Subject: Re: [Haskell-cafe] Laziness question To: michael rice nowg...@yahoo.com Cc: haskell-cafe@haskell.org Date: Saturday, July 31, 2010, 12:38 PM On Sat, Jul 31, 2010 at 4:56 PM, michael rice nowg...@yahoo.com wrote: From: http://en.wikibooks.org/wiki/Haskell/Laziness Given two functions of one parameter, f and g, we say f is stricter than g if f x evaluates x to a deeper level than g x Exercises 1. Which is the stricter function? f x = length [head x] g x = length (tail x) Prelude let f x = length [head x] Prelude let g x = length (tail x) Prelude f undefined 1 Prelude g undefined *** Exception: Prelude.undefined Prelude So, g is stricter than f? Wouldn't both functions need to evaluate x to the same level, *thunk* : *thunk* to insure listhood? f x = length [head *thunk* : *thunk*] g x = length (tail *thunk* : *thunk*) Michael ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe Notice the two different kinds of brackets being used in f versus g :) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 7/31/10 12:59 , michael rice wrote: OK, in f, *length* already knows it's argument is a list. In g, *length* doesn't know what's inside the parens, extra evaluation there. So g is already ahead before we get to what's inside the [] and (). But since both still have eval x to *thunk* : *thunk*, g evaluates to a deeper level? The whole point of laziness is that f *doesn't* have to eval x. - -- brandon s. allbery [linux,solaris,freebsd,perl] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkxUXbgACgkQIn7hlCsL25X5dQCdFskJ8+DdIVnJtsYVAFJkHcHO yjEAoMuoKU2yXLKVcLFGumLb0IJAVxnx =5KJ5 -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On Sat, Jul 31, 2010 at 5:59 PM, michael rice nowg...@yahoo.com wrote: OK, in f, *length* already knows it's argument is a list. In g, *length* doesn't know what's inside the parens, extra evaluation there. So g is already ahead before we get to what's inside the [] and (). According to the types, we already know both are lists. The question is, of course, what kind of list. But since both still have eval x to *thunk* : *thunk*, g evaluates to a deeper level? Michael I think this question is being quite sneaky. The use of head and tail is pretty much irrelevant. Try the pointfree versions: f = length . (:[]) . head g = length . tail and see if that helps you see why f is lazier than g. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
On 10-07-31 01:30 PM, Brandon S Allbery KF8NH wrote: On 7/31/10 12:59 , michael rice wrote: But since both still have eval x to *thunk* : *thunk*, g evaluates to a deeper level? The whole point of laziness is that f *doesn't* have to eval x. To elaborate, in computer-friendly syntax: f x = length (red_herring : []) length cares about cons cells (:) and nil [] only. You have already hardcoded exactly those. Enough said... err, enough evaluated. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
From Hoogle: Query: (:[]) Error: unexpected : expecting #, ,, forall, (, [, ! or ) Bad symbol Prelude let h = length . (:[]) . head Prelude h undefined 1 Prelude :t (:[]) (:[]) :: a - [a] Prelude h [] 1 this comes as a surprise Prelude Are you saying: [ head x ] - [ *thunk* ] and length [ *thunk* ] - 1, independent of what *thunk* is, even head [], i.e., *thunk* never needs be evaluated? Michael --- On Sat, 7/31/10, Ben Millwood hask...@benmachine.co.uk wrote: From: Ben Millwood hask...@benmachine.co.uk Subject: Re: [Haskell-cafe] Laziness question To: michael rice nowg...@yahoo.com Cc: haskell-cafe@haskell.org Date: Saturday, July 31, 2010, 1:47 PM On Sat, Jul 31, 2010 at 5:59 PM, michael rice nowg...@yahoo.com wrote: OK, in f, *length* already knows it's argument is a list. In g, *length* doesn't know what's inside the parens, extra evaluation there. So g is already ahead before we get to what's inside the [] and (). According to the types, we already know both are lists. The question is, of course, what kind of list. But since both still have eval x to *thunk* : *thunk*, g evaluates to a deeper level? Michael I think this question is being quite sneaky. The use of head and tail is pretty much irrelevant. Try the pointfree versions: f = length . (:[]) . head g = length . tail and see if that helps you see why f is lazier than g. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 7/31/10 14:24 , michael rice wrote: Are you saying: [ head x ] - [ *thunk* ] and length [ *thunk* ] - 1, independent of what *thunk* is, even head [], i.e., *thunk* never needs be evaluated? Exactly. (I was being cagey because the first response was cagey, possibly suspecting a homework question although it seems like an odd time for it.) length not only does not look inside of the thunk, it *can't* look inside it; all it knows is that it has a list, it specifically does *not* know what that list can hold. So the only thing it can do is count the number of unknown somethings in the list. - -- brandon s. allbery [linux,solaris,freebsd,perl] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkxUa54ACgkQIn7hlCsL25XVpgCeIxWwVWhjYQQ86uE2JeJD7mCB mKUAn3WwhrgrYyudv/E8pn5a0HB4gLA9 =H++/ -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
michael rice wrote: f x = length [head x] g x = length (tail x) Wouldn't both functions need to evaluate x to the same level, *thunk* : *thunk* to insure listhood? There is no need to insure listhood at run time, since Haskell is statically typed. Tillmann ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
Subtle stuff. Thanks, everyone, for your patience. You've been VERY helpful. Great list! Michael --- On Sat, 7/31/10, Brandon S Allbery KF8NH allb...@ece.cmu.edu wrote: From: Brandon S Allbery KF8NH allb...@ece.cmu.edu Subject: Re: [Haskell-cafe] Laziness question To: haskell-cafe@haskell.org Date: Saturday, July 31, 2010, 2:29 PM -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 7/31/10 14:24 , michael rice wrote: Are you saying: [ head x ] - [ *thunk* ] and length [ *thunk* ] - 1, independent of what *thunk* is, even head [], i.e., *thunk* never needs be evaluated? Exactly. (I was being cagey because the first response was cagey, possibly suspecting a homework question although it seems like an odd time for it.) length not only does not look inside of the thunk, it *can't* look inside it; all it knows is that it has a list, it specifically does *not* know what that list can hold. So the only thing it can do is count the number of unknown somethings in the list. - -- brandon s. allbery [linux,solaris,freebsd,perl] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkxUa54ACgkQIn7hlCsL25XVpgCeIxWwVWhjYQQ86uE2JeJD7mCB mKUAn3WwhrgrYyudv/E8pn5a0HB4gLA9 =H++/ -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
Brandon S Allbery KF8NH wrote: michael rice wrote: Are you saying: [ head x ] - [ *thunk* ] and length [ *thunk* ] - 1, independent of what *thunk* is, even head [], i.e., *thunk* never needs be evaluated? Exactly. (I was being cagey because the first response was cagey, possibly suspecting a homework question although it seems like an odd time for it.) length not only does not look inside of the thunk, it *can't* look inside it; all it knows is that it has a list, it specifically does *not* know what that list can hold. So the only thing it can do is count the number of unknown somethings in the list. Not entirely true: stupidlyStrictLength :: [a] - Integer stupidlyStrictLength [] = 0 stupidlyStrictLength (x:xs) = x `seq` 1 + stupidlyStrictLength xs Though, of course, if we actually wanted this function we should use an accumulator in order to avoid stack overflow when evaluating the (1+(1+...0)) thunk at the end. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Laziness question
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 7/31/10 16:58 , wren ng thornton wrote: Brandon S Allbery KF8NH wrote: michael rice wrote: Are you saying: [ head x ] - [ *thunk* ] and length [ *thunk* ] - 1, independent of what *thunk* is, even head [], i.e., *thunk* never needs be evaluated? Exactly. (I was being cagey because the first response was cagey, possibly suspecting a homework question although it seems like an odd time for it.) length not only does not look inside of the thunk, it *can't* look inside it; all it knows is that it has a list, it specifically does *not* know what that list can hold. So the only thing it can do is count the number of unknown somethings in the list. Not entirely true: stupidlyStrictLength :: [a] - Integer stupidlyStrictLength [] = 0 stupidlyStrictLength (x:xs) = x `seq` 1 + stupidlyStrictLength xs Given all the messes seq makes (hey, go behind the compiler's back and touch this arbitrary value of arbitrary type), I generally consider it to be unsafeSeq :) - -- brandon s. allbery [linux,solaris,freebsd,perl] allb...@kf8nh.com system administrator [openafs,heimdal,too many hats] allb...@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkxUlg4ACgkQIn7hlCsL25U41ACgy88GrDKrhfhNn8IiwYPA92qw Kn0AnilNyNJsPZXKIp86NEuWW4ECLVuv =hsLW -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe