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

Reply via email to