Proposal: making inits and tails less strict

Hello, I would like to propose making inits and tails less strict: inits :: [a] -> [[a]] -inits [] = [[]] -inits (x:xs) = [[]] ++ map (x:) (inits xs) +inits xs = [] : case xs of + [] -> [] + x:xs -> map (x:) (inits xs) tails :: [a] -> [[a]] -tails [] = [[]] -tails xxs@(_:xs) = xxs : tails xs +tails xxs = xxs : case xxs of + [] -> [] + _:xs -> tails xs Having a lazier inits allows the elegant: nats = map length (inits nats) which loops for the current definition. This definition was due to John Tromp: http://www.mail-archive.com/haskell@haskell.org/msg21044.html Discussion deadline: 2 weeks. Regards, Bas

On Thu, 17 Mar 2011, Bas van Dijk wrote:
Hello,
I would like to propose making inits and tails less strict:
http://hackage.haskell.org/packages/archive/utility-ht/0.0.6/doc/html/Data-L... Maybe you find more inspirations for proposals in that module. ;-)

Could the strictness properties be stated in the specification (i.e.
include some QuickCheck properties that define the strictness)
On Thu, Mar 17, 2011 at 12:25 PM, Bas van Dijk
Hello,
I would like to propose making inits and tails less strict:
inits :: [a] -> [[a]] -inits [] = [[]] -inits (x:xs) = [[]] ++ map (x:) (inits xs) +inits xs = [] : case xs of + [] -> [] + x:xs -> map (x:) (inits xs)
tails :: [a] -> [[a]] -tails [] = [[]] -tails xxs@(_:xs) = xxs : tails xs +tails xxs = xxs : case xxs of + [] -> [] + _:xs -> tails xs
Having a lazier inits allows the elegant: nats = map length (inits nats) which loops for the current definition. This definition was due to John Tromp: http://www.mail-archive.com/haskell@haskell.org/msg21044.html
Discussion deadline: 2 weeks.
Regards,
Bas
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 17 March 2011 21:09, Don Stewart
Could the strictness properties be stated in the specification (i.e. include some QuickCheck properties that define the strictness)
Good point. I will add the following strictness properties to the docs: inits ⊥ = [] : ⊥ tails ⊥ = ⊥ : ⊥ I'm not sure if we should add QC properties to the docs but we can have: prop_lazyInits xs = head (inits xs) == [] prop_isConsTails xs = case tails xs of [] → False _:_ → True Bas

On 03/18/11 04:06, Bas van Dijk wrote:
On 17 March 2011 21:09, Don Stewart
wrote: Could the strictness properties be stated in the specification (i.e. include some QuickCheck properties that define the strictness)
Good point. I will add the following strictness properties to the docs:
inits ⊥ = [] : ⊥ tails ⊥ = ⊥ : ⊥
I'm not sure if we should add QC properties to the docs but we can have:
prop_lazyInits xs = head (inits xs) == [] ...
By the way, QuickCheck can't really check laziness properties. It always provides finite, non-bottom input. (Well unless you make a generator that is somewhat out of its usual mold.) I think there's a library like "StrictCheck" that is meant to check strictness/laziness properties? For the Report, I sort of like the idea of just writing things like you said
inits ⊥ = [] : ⊥ tails ⊥ = ⊥ : ⊥
Although consider, it's been interpreted that the Report already has binding strictness requirements (strictness must be equivalent to the Report's implementation). We might want to change that means-of-specification if some other means is better. I think that's a good, unambiguous means though, unless we *want* the Report to underspecify strictness. Other thought about the proposal: Often, changing strictness has unintuitive effects on performance (I don't remember if that came up for this particular proposal sometime in the past, or for some different list function that libraries@ had been wishing were slightly lazier).

On 3/17/11 3:25 PM, Bas van Dijk wrote:
I would like to propose making inits and tails less strict:
inits :: [a] -> [[a]] -inits [] = [[]] -inits (x:xs) = [[]] ++ map (x:) (inits xs) +inits xs = [] : case xs of + [] -> [] + x:xs -> map (x:) (inits xs)
tails :: [a] -> [[a]] -tails [] = [[]] -tails xxs@(_:xs) = xxs : tails xs +tails xxs = xxs : case xxs of + [] -> [] + _:xs -> tails xs
Having a lazier inits allows the elegant: nats = map length (inits nats) which loops for the current definition. This definition was due to John Tromp: http://www.mail-archive.com/haskell@haskell.org/msg21044.html
+1. -- Live well, ~wren

+1
On Thu, Mar 17, 2011 at 3:25 PM, Bas van Dijk
Hello,
I would like to propose making inits and tails less strict:
inits :: [a] -> [[a]] -inits [] = [[]] -inits (x:xs) = [[]] ++ map (x:) (inits xs) +inits xs = [] : case xs of + [] -> [] + x:xs -> map (x:) (inits xs)
tails :: [a] -> [[a]] -tails [] = [[]] -tails xxs@(_:xs) = xxs : tails xs +tails xxs = xxs : case xxs of + [] -> [] + _:xs -> tails xs
Having a lazier inits allows the elegant: nats = map length (inits nats) which loops for the current definition. This definition was due to John Tromp: http://www.mail-archive.com/haskell@haskell.org/msg21044.html
Discussion deadline: 2 weeks.
Regards,
Bas
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 18 March 2011 06:25, Bas van Dijk
I would like to propose making inits and tails less strict:
inits :: [a] -> [[a]] -inits [] = [[]] -inits (x:xs) = [[]] ++ map (x:) (inits xs) +inits xs = [] : case xs of + [] -> [] + x:xs -> map (x:) (inits xs)
tails :: [a] -> [[a]] -tails [] = [[]] -tails xxs@(_:xs) = xxs : tails xs +tails xxs = xxs : case xxs of + [] -> [] + _:xs -> tails xs
Having a lazier inits allows the elegant: nats = map length (inits nats) which loops for the current definition. This definition was due to John Tromp: http://www.mail-archive.com/haskell@haskell.org/msg21044.html
I'm not against this proposal, but am just curious: is there any reason/need for this lazier definition apart from an elegant (but possibly not actually needed/useful) trick? -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On Thu, Mar 17, 2011 at 7:58 PM, Ivan Lazar Miljenovic < ivan.miljenovic@gmail.com> wrote:
On 18 March 2011 06:25, Bas van Dijk
wrote: I would like to propose making inits and tails less strict:
inits :: [a] -> [[a]] -inits [] = [[]] -inits (x:xs) = [[]] ++ map (x:) (inits xs) +inits xs = [] : case xs of + [] -> [] + x:xs -> map (x:) (inits xs)
tails :: [a] -> [[a]] -tails [] = [[]] -tails xxs@(_:xs) = xxs : tails xs +tails xxs = xxs : case xxs of + [] -> [] + _:xs -> tails xs
Having a lazier inits allows the elegant: nats = map length (inits nats) which loops for the current definition. This definition was due to John Tromp: http://www.mail-archive.com/haskell@haskell.org/msg21044.html
I'm not against this proposal, but am just curious: is there any reason/need for this lazier definition apart from an elegant (but possibly not actually needed/useful) trick?
In general with the standard library definitions have been made as lazy as they reasonably can. Here, clearly, the initial [] doesn't depend on the argument being resolved to a cons cell or nil. For me this is interesting mostly because of the nearly-comonadic extend :: ([a] -> b) -> [a] -> [b] extend f = map f . tails which I would like to be as productive as possible. -Edward
participants (7)
-
Bas van Dijk
-
Don Stewart
-
Edward Kmett
-
Henning Thielemann
-
Isaac Dupree
-
Ivan Lazar Miljenovic
-
wren ng thornton