Sunday 1 May 2016

Haskell: Ord type class


Ord class define comparison operators < <= > >=; min, max, and compare. Anything that is an instance of Ord can be sorted by Data.List.sort function.

You can’t apply comparison operators on types that don’t derive Ord class.

For Example, In the following snippet, Employee type don’t derives Ord class, so when you try to compare you will end up in error.

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

Prelude> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )
Ok, modules loaded: CustomTypes.
*CustomTypes> 
*CustomTypes> let engineer1 = Engineer "Hare" "Ram" 1
*CustomTypes> let engineer2 = Engineer "Rama" "Krishna" 1
*CustomTypes> 
*CustomTypes> engineer1 > engineer2

<interactive>:7:11:
    No instance for (Ord Employee) arising from a use of >
    In the expression: engineer1 > engineer2
    In an equation for it: it = engineer1 > engineer2
*CustomTypes> 


To get rid of above error, your type must derive Ord class.

Prelude> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )
Ok, modules loaded: CustomTypes.
*CustomTypes> 
*CustomTypes> let engineer1 = Engineer "Hare" "Ram" 1
*CustomTypes> let engineer2 = Engineer "Rama" "Krishna" 1
*CustomTypes> 
*CustomTypes> engineer1 > engineer2

<interactive>:7:11:
    No instance for (Ord Employee) arising from a use of >
    In the expression: engineer1 > engineer2
    In an equation for it: it = engineer1 > engineer2
*CustomTypes> 


By deriving the Ord class, you can get default implementation for comparison functions. If you want you can override this behaviour using instance statement.

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)


    {- Overriding == functionality -}
    instance Eq Employee where
        (==) (Engineer fName1 lName1 id1) (Engineer fName2 lName2 id2) = (id1 == id2) 
        (==) (Manager fName1 lName1 id1 noOfReportees1) (Manager fName2 lName2 id2 noOfReportees2) = (id1 == id2) 
        (==) (Director fName1 lName1 id1 noOfReportees1) (Director fName2 lName2 id2 noOfReportees2) = (id1 == id2) 

    {- Overriding Ord behavior -}
    instance Ord Employee where
        (<) (Engineer fName1 lName1 id1) (Engineer fName2 lName2 id2) = (id1 < id2) 
        (<) (Manager fName1 lName1 id1 noOfReportees1) (Manager fName2 lName2 id2 noOfReportees2) = (id1 < id2) 
        (<) (Director fName1 lName1 id1 noOfReportees1) (Director fName2 lName2 id2 noOfReportees2) = (id1 < id2) 

        (<=) (Engineer fName1 lName1 id1) (Engineer fName2 lName2 id2) = (id1 <= id2) 
        (<=) (Manager fName1 lName1 id1 noOfReportees1) (Manager fName2 lName2 id2 noOfReportees2) = (id1 <= id2) 
        (<=) (Director fName1 lName1 id1 noOfReportees1) (Director fName2 lName2 id2 noOfReportees2) = (id1 <= id2) 

        (>) (Engineer fName1 lName1 id1) (Engineer fName2 lName2 id2) = (id1 > id2) 
        (>) (Manager fName1 lName1 id1 noOfReportees1) (Manager fName2 lName2 id2 noOfReportees2) = (id1 > id2) 
        (>) (Director fName1 lName1 id1 noOfReportees1) (Director fName2 lName2 id2 noOfReportees2) = (id1 > id2) 

        (>=) (Engineer fName1 lName1 id1) (Engineer fName2 lName2 id2) = (id1 == id2) 
        (>=) (Manager fName1 lName1 id1 noOfReportees1) (Manager fName2 lName2 id2 noOfReportees2) = (id1 == id2) 
        (>=) (Director fName1 lName1 id1 noOfReportees1) (Director fName2 lName2 id2 noOfReportees2) = (id1 == id2) 

        (min) engineer1@(Engineer fName1 lName1 id1) engineer2@(Engineer fName2 lName2 id2) = if (engineer1 <= engineer2) then engineer1 else engineer2
        (max) engineer1@(Engineer fName1 lName1 id1) engineer2@(Engineer fName2 lName2 id2) = if (engineer1 >= engineer2) then engineer1 else engineer2


Prelude> :load CustomTypes.hs
[1 of 1] Compiling CustomTypes      ( CustomTypes.hs, interpreted )
Ok, modules loaded: CustomTypes.
*CustomTypes> 
*CustomTypes> let engineer1 = Engineer "Hari" "Krishna" 1
*CustomTypes> let engineer2 = Engineer "Tushar" "Goyal" 23
*CustomTypes> let enginner3 = Engineer "Phalgun" "Garimella" 5
*CustomTypes> let engineer4 = Engineer "Prasob" "Muthur" 3
*CustomTypes> let engineer5 = Engineer "Sunil" "Kumar" 30
*CustomTypes> 
*CustomTypes> min engineer1 engineer2
Engineer "Hari" "Krishna" 1
*CustomTypes> 
*CustomTypes> max engineer1 engineer2
Engineer "Tushar" "Goyal" 23
*CustomTypes> 
*CustomTypes> engineer5 > engineer4
True
*CustomTypes> 


Anything that is an instance of Ord can be sorted by Data.List.sort.

*CustomTypes> let engineer1 = Engineer "Hari" "Krishna" 1
*CustomTypes> let engineer2 = Engineer "Tushar" "Goyal" 23
*CustomTypes> let engineer3 = Engineer "Phalgun" "Garimella" 5
*CustomTypes> let engineer4 = Engineer "Prasob" "Muthur" 3
*CustomTypes> let engineer5 = Engineer "Sunil" "Kumar" 30
*CustomTypes> 
*CustomTypes> let employees = [engineer1, engineer2, engineer3, engineer4, engineer5]
*CustomTypes> 
*CustomTypes> import Data.List
*CustomTypes Data.List> sort employees
[Engineer "Hari" "Krishna" 1,Engineer "Prasob" "Muthur" 3,Engineer "Phalgun" "Garimella" 5,Engineer "Tushar" "Goyal" 23,Engineer "Sunil" "Kumar" 30]



Since all my comparison definitions are based on id field, when I call ‘sort employees’, it sorts employees based on id field.

Previous                                                 Next                                                 Home

No comments:

Post a Comment