> It is somewhat inconvenient but its not unfounded. You can use the
> technique used in the Show class in the Prelude to handle showing
> things of type String. Erik Meijer has written an exposition of this
> (which I can't find just now.)
>
> mike
>
> Here's an example. It elides the efficiency hack of using function
> composition instead of (++).
OK, thanks. Essentially, you recommend creating an instance for
(Pretty a) => Pretty [a]
and using that instead. Unfortunately, I really do want different
behaviour for lists of characters (which should print out as strings) and
for lists of most other things.
I suppose the thing to do is to create dummy classes, like so: (in
untested pseoudocode):
> class IsChar a where
> toChar :: a -> Char
> toString :: [a] -> String
> instance IsChar Char where
> toChar = id
> toString = id
> instance (PrettyIsChar a) => Pretty [a] where
> showDoc x = text (toString x)
> class IsNotChar a
> instance (Pretty a, IsNotChar a) => Pretty [a] where
> showDoc x = ...
> data Dummy = Foo | Bar
> instance IsNotChar Dummy
> instance Pretty Dummy where ...
and then lists of Dummy's print out correctly. Hmm. Still annoying,
though workable. As a bonus, we get to select between different methods
of dealing with lists if we want.
This could also be done with overlapping instances, of course. It gives
me a new appreciation for them...
Thanks!
--Dylan
(old example below)
> data DOC = DOC String deriving (Show)
> unDoc (DOC s) = s
>
> text :: String -> DOC
> text = DOC
>
> showDocS :: Pretty a => a -> String
> showDocS = unDoc . showDoc
>
> class Pretty a where
> showDoc :: a -> DOC
> showListDoc :: [a] -> DOC
>
> showListDoc [] = DOC "[]"
> showListDoc (x:xs) = DOC ("[" ++ showDocS x ++ showl xs)
> where showl [] = "]"
> showl (x:xs) = "," ++ showDocS x ++ showl xs
>
> instance Pretty Int where
> showDoc = text . show
>
> instance Pretty Char where
> showDoc ch = DOC ('\'':ch:"\'")
> showListDoc = DOC
>
> instance Pretty a => Pretty [a] where
> showDoc = showListDoc
>