A type class is
a set of functions, along with their signature. By using the keyword ‘class’,
you can define a type class.
Syntax
class
TypeClassName a where
function1 :: type1
function2 :: type2
....
....
functionN :: typeN
CustomTypeClasses.hs
class Equal a where isEquals :: a -> a -> Bool
Above snippet says that I defined a type
class Equal, and this type class declare one function isEquals, which takes two
arguments of type ‘a’ and return True if they are equal, else False. 'a' is a
type variable, it refers instance types of this Type class Equal.
Go to GHCi prompt and get the type of
the function ‘isEquals’.
*Main> :t isEquals
isEquals :: Equal a => a -> a
-> Bool
Observe the signature, it is telling
variable ‘a’ is of type Equal.
What
is instance type?
An instance type of a typeclass is any
type that implements the functions defined in the typeclass.
Prelude> :load CustomTypeClasses.hs [1 of 1] Compiling Main ( CustomTypeClasses.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> *Main> :t isEquals isEquals :: Equal a => a -> a -> Bool
isEquals
:: Equal a => a -> a -> Bool
You can interpret above statement like,
type 'a' must be an instance of Equal, and isEqual method takes two arguments
of type 'a' and return True if they are equal, else False.
Define
isEquals method for custom type
I am going to define isEquals method for
my custom types Engineer, Manager, Director.
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
CustomTypeClasses.hs
import CustomTypes class Equal a where isEquals :: a -> a -> Bool instance Equal Employee where isEquals (Engineer firstName1 lastName1 empId1) (Engineer firstName2 lastName2 empId2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2) isEquals (Manager firstName1 lastName1 empId1 noOfReportees1) (Manager firstName2 lastName2 empId2 noOfReportees2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2) isEquals (Director firstName1 lastName1 empId1 noOfReportees1) (Director firstName2 lastName2 empId2 noOfReportees2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2)
*Main> :load CustomTypeClasses.hs [1 of 2] Compiling CustomTypes ( CustomTypes.hs, interpreted ) [2 of 2] Compiling Main ( CustomTypeClasses.hs, interpreted ) Ok, modules loaded: Main, CustomTypes. *Main> *Main> let engineer1 = Engineer "Hari Krishna" "Gurram" 1 *Main> let engineer2 = Engineer "Hari" "Gurram" 1 *Main> let engineer3 = Engineer "Hari Krishna" "Gurram" 1 *Main> *Main> isEquals engineer1 engineer2 False *Main> isEquals engineer1 engineer3 True *Main>
Suppose, you want to add isNotEquals
function, which return True, when elements are not equal, False when elements
are equal.
CustomTypeClasses.hs
import CustomTypes class Equal a where isEquals :: a -> a -> Bool isNotEquals :: a -> a -> Bool instance Equal Employee where isEquals (Engineer firstName1 lastName1 empId1) (Engineer firstName2 lastName2 empId2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2) isEquals (Manager firstName1 lastName1 empId1 noOfReportees1) (Manager firstName2 lastName2 empId2 noOfReportees2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2) isEquals (Director firstName1 lastName1 empId1 noOfReportees1) (Director firstName2 lastName2 empId2 noOfReportees2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2)
Try to load CustomTypeClasses.hs file,
compiler gives you warning like isNotEquals is not implemented for type
Employee.
*Main> :load CustomTypeClasses.hs [1 of 2] Compiling CustomTypes ( CustomTypes.hs, interpreted ) [2 of 2] Compiling Main ( CustomTypeClasses.hs, interpreted ) CustomTypeClasses.hs:8:10: Warning: No explicit implementation for ‘isNotEquals’ In the instance declaration for ‘Equal Employee’ Ok, modules loaded: Main, CustomTypes.
One way to get rid of this warning is
implement 'isNotEquals' function for all Engineer, Manager, Director. Another
simple way to implement is, any way we know isNotEquals function is completely
opposite to isEquals function, we can add following line in
CustomTypeClasses.hs file.
isNotEquals
:: a -> a -> Bool
isNotEquals
x y = not (isEquals x y)
isNotEquals is not( isEquals) function, (Given default implementation), that means types that implement isEquals function, no need to
implement isNotEuals function. This is called providing default implementation
for a type class function.
CustomTypeClasses.hs
import CustomTypes class Equal a where isEquals :: a -> a -> Bool isNotEquals :: a -> a -> Bool isNotEquals x y = not (isEquals x y) instance Equal Employee where isEquals (Engineer firstName1 lastName1 empId1) (Engineer firstName2 lastName2 empId2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2) isEquals (Manager firstName1 lastName1 empId1 noOfReportees1) (Manager firstName2 lastName2 empId2 noOfReportees2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2) isEquals (Director firstName1 lastName1 empId1 noOfReportees1) (Director firstName2 lastName2 empId2 noOfReportees2) = (firstName1 == firstName2) && (lastName1 == lastName2) && (empId1 == empId2)
*Main> :load CustomTypeClasses.hs [1 of 2] Compiling CustomTypes ( CustomTypes.hs, interpreted ) [2 of 2] Compiling Main ( CustomTypeClasses.hs, interpreted ) Ok, modules loaded: Main, CustomTypes. *Main> *Main> let engineer1 = Engineer "Hari Krishna" "Gurram" 1 *Main> let engineer2 = Engineer "Hari" "Gurram" 1 *Main> *Main> isEquals engineer1 engineer2 False *Main> *Main> isNotEquals engineer1 engineer2 True *Main>
No comments:
Post a Comment