Search code examples
haskelllispschemes-expression

Bug in s-expr printing function


To practice my Haskell skills, I'm following the Write Yourself a Scheme tutorial. I've implemented a parser for s-expressions, but I'm having trouble with the printing function.

When I run the following program

main :: IO ()
main  =  do args <- getArgs
            putStrLn $ readExpr (args !! 0)

it parses the s-expressions correctly, but when I define my own shows instead of deriving it, I get erroneous output for nested lists and lists inside vectors:

$ ./parser "(1 (2) 3)"
(1 (2 3))
$ ./parser "#(1 (2) 3)"
#(1 (2 3))
$ ./parser "(1 (2 (3)) 4)"
(1 (2 (3 4)))
$ ./parser "(1 (2 (3)) (4))"
(1 (2 (3 (4))))

Other cases and nested vectors work fine, though:

lars@zygmunt:~/src/scm48$ ./parser "(1 #(2) 3)"
(1 #(2) 3)
lars@zygmunt:~/src/scm48$ ./parser "#(1 #(2) 3)"
#(1 #(2) 3)
lars@zygmunt:~/src/scm48$ ./parser "(1 (2 3))"
(1 (2 3))

I've changed the representation of LispVal to include Nil and Pair constructors instead of List and DottedList, as these match better with the Scheme data model. Printing lists is done by

showsVal :: Value -> ShowS
showsVal Nil              =  ("()" ++)
showsVal (Pair x y)       =  ("(" ++) . showsPair x y . (++ ")")
showsVal (String s)       =  shows s
showsVal (Symbol n)       =  (n ++)
showsVal (Number x)       =  shows x
showsVal (Boolean True)   =  ("#t" ++)
showsVal (Boolean False)  =  ("#f" ++)
showsVal (Vector v)       =  ("#(" ++) . showsVec v . (")" ++)

showsPair x Nil         =  showsVal x
showsPair x (Pair y z)  =  (showsVal x) . (" " ++) . showsPair y z
showsPair x y           =  (showsVal x) . (" . " ++) . (showsVal y)

showsVec []      =  id
showsVec [x]     =  shows x
showsVec (x:xs)  =  shows x . (" " ++) . showsVec xs

I suspect the error is in showsPair, but I just can't figure it out.


Solution

  • I found out myself:

    showsVal (Pair x y)  =  ("(" ++) . showsPair x y . (++ ")")
    

    should have been

    showsVal (Pair x y)  =  ("(" ++) . showsPair x y . (")" ++)
                                                    --  ^^^^^^