Saturday 30 April 2016

Haskell: Smart constructors


Smart constructors is a technique to place constraints on on the construction of values by using smart constructors. Let me try to explain with an example.

Person.hs
type Height = Float
type Weight = Float
type Name = String

data Category = Male | Female

data Person = Person Name Category Weight Height deriving Show
 
Just observe the definition of type Person, do you think anything wrong with this definition. Yes it is, value constructor Person has fields like Weight, Height Which are of type Float. Since we are not doing any validation on these types, user can able to define a Person variable by giving –ve values to Height and Weight fields, which is completely wrong.
Prelude> :load Person.hs
[1 of 1] Compiling Main             ( Person.hs, interpreted )
Ok, modules loaded: Main.
*Main> 
*Main> let person1 = Person "Srinu" Male (-16) (-19.8)
*Main> 
*Main> person1
Person "Srinu" Male (-16.0) (-19.8)


Smarter constructors
Smart constructors are nothing but functions that build values of the required type, but perform some extra checks when the value is constructed.

Person.hs
module Person (getPerson) where
    type Height = Float
    type Weight = Float
    type Name = String

    data Category = Male | Female deriving Show

    data Person = Person Name Category Weight Height deriving Show

    getPerson :: Name -> Category -> Weight -> Height -> Person
    getPerson name category weight height
        | (weight < 0) || (weight > 1000) = error "Invalid Weight"
        | (height < 0) || (height > 10) = error "Invalid Height"
        | otherwise = Person name category weight height


Observe above snippet, I hide the definition of Person from this module. Outside of this module must call the function getPerson to get Person variable. getPerson function performs checks on the arguments before returning Person variable.
Prelude> :load Person.hs
[1 of 1] Compiling Person           ( Person.hs, interpreted )
Ok, modules loaded: Person.
*Person> 
*Person> 
*Person> getPerson "Hari" Male 71 5.8
Person "Hari" Male 71.0 5.8
*Person> 
*Person> getPerson "Hari" Male 71 (-10)
*** Exception: Invalid Height
*Person> 
*Person> getPerson "Hari" Male (-9) (-10)
*** Exception: Invalid Weight
*Person> 


 
Previous                                                 Next                                                 Home

No comments:

Post a Comment