[Haskell-cafe] Re: Software Tools in Haskell

Tommy M McGuire mcguire at crsr.net
Wed Dec 12 18:36:36 EST 2007


apfelmus wrote:
> Tommy M McGuire wrote:
>> (Plus, interact is scary. :-D )
> 
> You have a scary feeling for a moment, then it passes. ;)
> 
> 
>   tabwidth = 4
> 
>      -- tabstop !! (col-1) == there is a tabstop at column  col
>      -- This is an infinite list, so no need to limit the line width
>   tabstops  = map (\col -> col `mod` tabwidth == 1) [1..]
> 
>      -- calculate spaces needed to fill to the next tabstop in advance
>   tabspaces = snd $ mapAccumR addspace [] tabstops
>   addspace cs isstop = let cs'=' ':cs in (if isstop then [] else cs',cs')

Are you using mapAccumR (mapAccumR? (!)) to share space among the space 
strings?  If so, wouldn't this be better:

tabstops = map (\col -> col `mod` tabwidth == 1) [1..tabwidth]
tabspaces = cycle $ snd $ mapAccumR addspace [] tabstops

On the other hand, wouldn't this make for less head scratching:

tabspaces = map (\col -> replicate (spacesFor col) ' ') [1..]
   where
   spacesFor col = tabwidth - ((col - 1) `mod` tabwidth)

>   main = interact $ unlines . map detabLine . lines
>      where
>      detabLine = concat $ zipWith replace tabspaces

I think you mean "concat . zipWith...".   (You're doing this from 
memory, aren't you?)

>      replace cs '\t' = cs     -- replace with adequate number of spaces
>      replace _  char = [char] -- pass through
> 
> 
> How about that?

It doesn't produce the same output, although I almost like it enough not 
to care:

$ od -a test
0000000  ht   c   o   l  sp   1  ht   2  ht   3   4  ht   r   e   s   t
0000020  nl
0000021
$ runhaskell detab.hs <test
     col 1   2   34  rest
$ runhaskell detab2.hs <test
     col 1  2    34 rest

It's counting tabs before expanding rather than after?

-- 
Tommy M. McGuire
mcguire at crsr.net


More information about the Haskell-Cafe mailing list