Hi,
Is there an explanation to this phenom
Wolfram Kahl wrote:
> To my surprise,
> the prelude definition of lines:
> > lines :: String -> [String]
> > lines "" = []
> > lines s = let (l, s') = break (== '\n') s
> > in l : case s' of
> > [] -> []
> > (_:s'') -> lines s''
> (for which I have not yet seen a derivation,
> and which is actually used in hugs, ghc, and hbc
> although the report allows more efficient implementations)
> not only is not much less cryptic than the definition I arrived at
> (and anybody would arrive at)
To me this definition is also natural in that lines,
being a converse of unlines, thus a converse of a
fold, can be expressed as an unfold. If Haskell has
provided unfold on non-empty lists as follows:
> unfoldr1 f x =
> case f x of Left y -> [y]
> Right (y,x') -> y : unfoldr1 f x'
then lines can be defined this way
> lines1 :: String -> [String]
> lines1 = unfoldr1 unConcLine
> where unConcLine s = let (l, s') = break (== '\n') s
> in case s' of [] -> Left l
> (_:s'') -> Right (l,s'')
where unConcLine is a converse of the coproduct of concLine and "".
The function concLine has appeared on your web page
(concLine xs ys = xs ++ '\n' : ys). I think I can come to a
derivation of it. It may be far less beautiful than your fold
version, though. :)
> > lines :: String -> [String]
> > lines = foldr f []
> > where
> > f '\n' xss = "" : xss
> > f x [] = [[x]]
> > f x (ys:yss) = (x:ys) : yss
I am curious why the Prelude version is less efficient than the
your fold version? It seems to me the fold version construct a
cons cell and deconstruct it immedately everytime it glues a
character to the first line, while the Prelude version only
wastes a pair cell for every line. Why is the Prelude version
slower? Can someone give an explanation?
sincerely,
Shin-Cheng Mu