Suspended
Suspended

Reputation: 1190

Haskell deriving Show for custom type

How can I tell haskell that when show is called on a list of variables of algebraic type, a "\n" should be inserted after each line?

type Customer = (Int, Int, [Int])

I tried to do this:

instance of Show Customer where
show x = x ++ "\n"

but apparently I can only create such instances for "data...." kind of things. How can I solve this?

I need to derive Show just for a list of Customers, so that when I display it, the output is easily readable, one customer per line.

Upvotes: 7

Views: 4908

Answers (2)

Stefan Holdermans
Stefan Holdermans

Reputation: 8050

A small addition to AndrewC's excellent answer:

6. Write a function that adds a new line to the textual representation of any type in the class Show:

display :: Show a => a -> String
display = flip shows "\n"

For example:

> display (2, 3, [5, 7, 11])
"(2,3,[5,7,11])\n"

Upvotes: 3

AndrewC
AndrewC

Reputation: 32455

To just display on different lines, don't change show, just do unlines (map show customerList). This will show each of them, then put them back together with newline characters inbetween.


However, you asked about changing show for a type synonym, so here are your options for that:

show is for basic serialisation of the data. If you want to do something different, you've got a few options:

  1. Write a function that does it in this instance.
  2. Make your own Display class and define how you like to lay things out in its display function.
  3. Use a newtype to wrap the data.
  4. Declare your own customer type.
  5. Add newlines later

    type Customer = (Int, Int, [Int])

Example 1

displayC :: Customer -> String
displayC = (++"\n").show

Example 2

{-# LANGUAGE TypeSynonymInstances,  FlexibleInstances #-}
class Display a where
  display :: a -> String

instance Display Customer where
   display x = show x ++ "\n"

(Notice you should say instance Display Customer rather than instance of Display Customer.)

Example output:

*Main> display ((3,4,[5,6])::Customer)
"(3,4,[5,6])\n"

Those language extensions should be used with caution, though.

Example 3

newtype Cust = Cust Customer
displayCust (Cust c) = show c ++ "\n"

Example 4

data CustomerTup = CTup Int Int [Int]
displayCTup (CTup a b cs) = show (a,b,cs) ++ "\n"

or even better,

data CustomerRec = CRec {custno::Int, custAge::Int, custMeasurements::[Int]}
  deriving Show
displayCRec r = show (custno r,custAge r,custMeasurements r) ++ "\n"

where you might even stick with the Show instance way of doing things. The data way is good because there's more type safety, and the record type stops you making trivial wrong position mistakes.

Example 5

stuff = unlines $ map show  [(1,2,[3,4]),(5,6,[7,8,9])]

or even

morestuff = unlines [show (1,2,[3,4]), 
                     show (5,6,[7,8,9]),
                     "are all more numbery than",
                     show (True,4,False)]

Upvotes: 10

Related Questions