Personal tools

Indent

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
(Some ideas for an indent(1)-like tool in Haskell)
 
(+cat)
 
(2 intermediate revisions by one user not shown)
Line 34: Line 34:
 
 
 
==================== Parser ====================
 
==================== Parser ====================
  +
<haskell>
 
main = do
 
main = do
 
print (f 10)
 
print (f 10)
Line 39: Line 40:
 
print (f 3735928559)
 
print (f 3735928559)
 
f x = sqrt (fromIntegral ((x * 10133123) `mod` 1231111121 :: Int))
 
f x = sqrt (fromIntegral ((x * 10133123) `mod` 1231111121 :: Int))
  +
</haskell>
   
   
Line 44: Line 46:
 
$ ghc -fno-code -ddump-parsed B.hs | sed '/^===/d'
 
$ ghc -fno-code -ddump-parsed B.hs | sed '/^===/d'
   
  +
<haskell>
 
main = do
 
main = do
 
print (f 10)
 
print (f 10)
Line 49: Line 52:
 
print (f 3735928559)
 
print (f 3735928559)
 
f x = sqrt (fromIntegral ((x * 10133123) `mod` 1231111121 :: Int))
 
f x = sqrt (fromIntegral ((x * 10133123) `mod` 1231111121 :: Int))
  +
</haskell>
   
 
Which is a reasonable result.
 
Which is a reasonable result.
Line 54: Line 58:
 
===Use ghc-api===
 
===Use ghc-api===
   
?
+
It may be possible to use ghc-api.
   
 
===Use Language.Haskell===
 
===Use Language.Haskell===
   
Downside is the lack of parsing the extensions we use. And it will also
+
For Haskell98, this program should do the trick:
strip comments.
+
<haskell>
  +
import Language.Haskell.Parser
  +
import Language.Haskell.Pretty
  +
  +
main = interact $ \s ->
  +
case parseModule s of
  +
ParseFailed loc str -> (show loc) ++ "\n"
  +
ParseOk m -> (prettyPrint m) ++ "\n"
  +
</haskell>
  +
  +
For example:
  +
$ ghc -O Ppr.hs -package haskell-src
  +
  +
$ ./a.out < Ppr.hs
  +
<haskell>
  +
module Main (main) where
  +
import Language.Haskell.Parser
  +
import Language.Haskell.Pretty
  +
main
  +
= interact $
  +
\ s ->
  +
case parseModule s of
  +
ParseFailed loc str -> (show loc) ++ "\n"
  +
ParseOk m -> (prettyPrint m) ++ "\n"
  +
</haskell>
  +
  +
Or:
  +
<haskell>
  +
main =
  +
let {
  +
x = 7;
  +
} in
  +
  +
return (
  +
x + x
  +
)
  +
</haskell>
  +
  +
Becomes:
  +
<haskell>
  +
module Main (main) where
  +
main = let x = 7 in return (x + x)
  +
</haskell>
  +
  +
===Lambdabot===
  +
  +
[[Lambdabot]] has a pretty printing plugin that can be used for similar purposes.
  +
It only takes a single line of input though.
  +
  +
lambdabot> pretty main=let{x=7;y=3;z=4}in case x+y of { _|z<2 -> 1}
  +
<haskell>
  +
main = let x = 7
  +
y = 3
  +
z = 4
  +
in case x + y of
  +
_ | z < 2 -> 1
  +
</haskell>
   
 
[[Category:Idioms]]
 
[[Category:Idioms]]
  +
[[Category:Tools]]

Latest revision as of 20:09, 18 January 2007

Contents

[edit] 1 Indenting Haskell Mechanically

indent(1) is a tool to format C program source. At the time of writing we have no such tool for Haskell in common use -- although this would be fairly easy to write, given the existing parsing and pretty printing libraries.

Here are some other solutions

[edit] 1.1 Emacs

Emacs has an indent mode. Though it is often considered poor at laying out Haskell code.

[edit] 1.2 Use GHC

GHC provides a --ddump-parsed flag. It can be used as follows. Note that it will strip comments -- so take care! It will also normalise values -- so 0xdeadbeef becomes a large decimal.

    main = do  {
        ;print (f 10)
                ;      print (f 20)
       ;print (f 0xdeadbeef)       
    }                                                                                                 
    f x = sqrt  ( fromIntegral 
            (x * 10133123 `mod` 
                        1231111121 :: Int ))

Running it through:

$ ghc -fno-code -ddump-parsed B.hs
                                     
==================== Parser ====================
 main = do                                       
          print (f 10)
          print (f 20)
          print (f 3735928559)
 f x = sqrt (fromIntegral ((x * 10133123) `mod` 1231111121 :: Int))


Postprocess:

$ ghc -fno-code -ddump-parsed B.hs | sed '/^===/d'
 main = do
          print (f 10)
          print (f 20)
          print (f 3735928559)
 f x = sqrt (fromIntegral ((x * 10133123) `mod` 1231111121 :: Int))

Which is a reasonable result.

[edit] 1.3 Use ghc-api

It may be possible to use ghc-api.

[edit] 1.4 Use Language.Haskell

For Haskell98, this program should do the trick:

import Language.Haskell.Parser
import Language.Haskell.Pretty
 
main = interact $ \s ->
    case parseModule s of
        ParseFailed loc str -> (show loc)      ++ "\n"
        ParseOk m           -> (prettyPrint m) ++ "\n"

For example:

$ ghc -O Ppr.hs -package haskell-src
$ ./a.out < Ppr.hs
module Main (main) where
import Language.Haskell.Parser
import Language.Haskell.Pretty
main
   = interact $
       \ s ->
         case parseModule s of
             ParseFailed loc str -> (show loc) ++ "\n"
             ParseOk m -> (prettyPrint m) ++ "\n"

Or:

 main =  
   let {
       x = 7;
          } in 
 
              return (
                x + x
                        )

Becomes:

 module Main (main) where
 main = let x = 7 in return (x + x)

[edit] 1.5 Lambdabot

Lambdabot has a pretty printing plugin that can be used for similar purposes. It only takes a single line of input though.

lambdabot> pretty main=let{x=7;y=3;z=4}in case x+y of { _|z<2 -> 1}

 main = let x = 7
            y = 3
            z = 4
        in case x + y of
            _ | z < 2 -> 1