Sunday, 1 May 2016

Haskell: Type class Show: Convert values to Strings


Show class is used to convert values to Strings. For example, You can convert Int, Bool, Double, any other custom types to readable String format using Show.
Prelude> :t show
show :: Show a => a -> String


Observe above snippet, it is stating that show method can take any value of type ‘a’ which is an instance of type class Show and return string representation of the value.
Prelude> show 10
"10"
Prelude> show 10.23
"10.23"
Prelude> show True
"True"
Prelude> show (1, 2, 3)
"(1,2,3)"
Prelude> 
Prelude> show [1, 2, 3]
"[1,2,3]"
Prelude> show ["Hello", "How", "are", "you"]
"[\"Hello\",\"How\",\"are\",\"you\"]"
Prelude> 
Prelude> show "Hello World"
"\"Hello World\""
Prelude> 


When I call show "Hello World", I got result like "\"Hello World\"", it is confusing, isn't it? It is because show generates a result that is suitable for a Haskell literal; it adds quotes and escaping suitable for inclusion in a Haskell program.

To see the output properly, call show function inside putStrLn function.  
Prelude> putStrLn (show "Hello World")
"Hello World"


Apply show on custom types
Just add the ‘deriving (Show)’ statement at the end of your custom type definition. It takes care everything.

CustomTypes.hs
module CustomTypes where
    type FirstName = String
    type LastName = String
    type EmpId = Integer
    type NoOfReportees = Integer

    {- Define an employee type -}
    data Employee = Engineer FirstName LastName EmpId
                   | Manager FirstName LastName EmpId NoOfReportees
                   | Director FirstName LastName EmpId NoOfReportees
                   deriving(Show)

Prelude> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )
Ok, modules loaded: CustomTypes.
*CustomTypes> 
*CustomTypes> let engineer1 = Engineer "Hari krishna" "Gurram" 1
*CustomTypes> let manager1 = Manager "Anand" "Bandaru" 213 345
*CustomTypes> 
*CustomTypes> show engineer1
"Engineer \"Hari krishna\" \"Gurram\" 1"
*CustomTypes> 
*CustomTypes> show manager1
"Manager \"Anand\" \"Bandaru\" 213 345"
*CustomTypes> 
*CustomTypes> putStrLn (show engineer1)
Engineer "Hari krishna" "Gurram" 1
*CustomTypes> 
*CustomTypes> putStrLn (show manager1)
Manager "Anand" "Bandaru" 213 345
*CustomTypes> 


Observe above output, by default show function displays all the field values in order.

What if you don’t want to display EmpId, NoOfReportees ?
Instead of deriving Show class, write your own definition for show function like below.
instance Show Employee where
    show (Engineer firstName lastName empId) = firstName ++ " : " ++ lastName
    show (Manager firstName lastName empId noOfReportees) = firstName ++ " : " ++ lastName ++ " : " ++ show noOfReportees
    show (Director firstName lastName empId noOfReportees) = firstName ++ " : " ++ lastName ++ " : " ++ show noOfReportees


CustomTypes.hs
module CustomTypes where
    type FirstName = String
    type LastName = String
    type EmpId = Integer
    type NoOfReportees = Integer

    {- Define an employee type -}
    data Employee = Engineer FirstName LastName EmpId
                   | Manager FirstName LastName EmpId NoOfReportees
                   | Director FirstName LastName EmpId NoOfReportees
                   
    instance Show Employee where
        show (Engineer firstName lastName empId) = firstName ++ " : " ++ lastName
        show (Manager firstName lastName empId noOfReportees) = firstName ++ " : " ++ lastName ++ " : " ++ show noOfReportees
        show (Director firstName lastName empId noOfReportees) = firstName ++ " : " ++ lastName ++ " : " ++ show noOfReportees

*CustomTypes> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )
Ok, modules loaded: CustomTypes.
*CustomTypes> 
*CustomTypes> let engineer1 = Engineer "Hari krishna" "Gurram" 123
*CustomTypes> let manager1 = Manager "Anand" "Bandaru" 213 34
*CustomTypes> 
*CustomTypes> show engineer1
"Hari krishna : Gurram"
*CustomTypes> 
*CustomTypes> show manager1
"Anand : Bandaru : 34"
*CustomTypes> 


Note
If you are using one custom type ‘A’ in other custom type ‘B’, To print (or) display the value of type ‘B’, type ‘A’ must derive Show.

CustomTypes.hs
module CustomTypes where
    type FirstName = String
    type LastName = String
    type EmpId = Integer
    type NoOfReportees = Integer

    {- Define an employee type -}
    data Employee = Engineer Person EmpId
                   | Manager Person EmpId NoOfReportees
                   | Director Person EmpId NoOfReportees
                   deriving Show

    data Person = Person FirstName LastName 


Try to load CustomTypes module, you will get following kind og error.

Prelude> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )

CustomTypes.hs:11:29:
    No instance for (Show Person)
      arising from the first field of Engineer (type Person)
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Show Employee)
Failed, modules loaded: none.


To resolve above error, let the Person type derive Show type class.

CustomTypes.hs
module CustomTypes where
    type FirstName = String
    type LastName = String
    type EmpId = Integer
    type NoOfReportees = Integer

    {- Define an employee type -}
    data Employee = Engineer Person EmpId
                   | Manager Person EmpId NoOfReportees
                   | Director Person EmpId NoOfReportees
                   deriving Show

    data Person = Person FirstName LastName deriving Show

Prelude> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )
Ok, modules loaded: CustomTypes.
*CustomTypes> 
*CustomTypes> let person1 = Person "Hari Krishna" "Gurram"
*CustomTypes> let employee1 = Engineer person1 123
*CustomTypes> 
*CustomTypes> employee1
Engineer (Person "Hari Krishna" "Gurram") 123
*CustomTypes> 





Previous                                                 Next                                                 Home

No comments:

Post a Comment