Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 336
Suspended Avatar asked Nov 19 '12 22:11

Suspended


People also ask

What does deriving show do in Haskell?

The second line, deriving (Eq, Show) , is called the deriving clause; it specifies that we want the compiler to automatically generate instances of the Eq and Show classes for our Pair type. The Haskell Report defines a handful of classes for which instances can be automatically generated.

How do you find type in Haskell?

If you need to figure out what the type of an object is in a Haskell program, I hope this is helpful. Note that if you are in GHCI, you can just put :type before your expression to determine the expression's type, or use :set +t to see the type of every expression in GHCI.

What is show in Haskell?

The shows functions return a function that prepends the output String to an existing String . This allows constant-time concatenation of results using function composition.

How can you explicitly specify the types of functions in your program in Haskell?

We can define our own types in Haskell using a data declaration, which we introduce via a series of examples (§4.2. 1). The type being defined here is Bool, and it has exactly two values: True and False.


1 Answers

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)]
like image 59
AndrewC Avatar answered Oct 18 '22 17:10

AndrewC