Show the components of the sum

Frank Atanassow franka@cs.uu.nl
Sat, 21 Sep 2002 14:55:24 +0200


David Roundy wrote (on 21-09-02 07:30 -0400):
> Here is what I'd like to do:
> 
> \begin{code}
> data D = A String | B String
> instance  Show D where
>     show = showD
> instance  Read D where
>     readsPrec _ = readsD
> readD s = (readsA s) ++ (readsB s)
> \end{code}
> 
> A is formatted like ``A string''.
> \begin{code}
> showD (A s) = "A " ++ s
> readsA s = [(A thestr, r) | ("A", x) <- mylex s,
>                             (thestr, r) <- mylex x]
> \end{code}
.. [ and similarly for B ] ...
> 
> The problem I have is that ghc complains because I've split up the
> definition of showD with readsA defined in between.  This surprised me,
> since it seemed that the code should still be unambiguous.
> 
> Is there some nice way around this,

There's no way to intersperse clauses of top-level declarations, no.

> or do I have to define a separate
> function for each constructor, and then have a list in one place (as I do
> with the readsD, in that case because pattern matching won't give me what I
> want), like:
> 
> showD (A s) = showA (A s)
> showD (B s) = showB (B s)

Almost. But then showA and showB are partial. It's better to do this:

  showA s = "A " ++ s

and similarly for B, and then:

  data D = A String | B String
  instance  Show D where
    show (A s) = showA s
    show (B s) = showB s
  instance  Read D where
    readsPrec _ = readsD
  readD s = (readsA s) ++ (readsB s)

What you are doing here basically is just assigning names to the branches of a
case-expression:

  h sum =
    case sum of
      Left x  -> ... x ...
      Right y -> ... y ...

<=

  h sum =
    case sum of
      Left x  -> (\x' -> ... x' ...) x
      Right y -> (\y' -> ... y' ...) y

<=

  h sum =
    let f x' = ... x' ...
        g y' = ... y' ...
    in  case sum of
          Left x -> f x
          Right y -> g y

<=

  f x' = ... x' ...

  g y' = ... y' ...

  h (Left x)  = f x
  h (Right y) = g y

-- 
Frank