Haskell Program to Call One Constructor from Another


In Haskell, we will call one constructor from another by using user-defined function. In the first example, we are going to use (newPerson name = Person name 10) constructor and in the second example, we are going to use (newPerson n a = Person { name = n, age = a }) constructor. In the third example, we are going to use (clonePerson p = p { name = name p ++ " clone" }) constructor and in the fourth example, we are going to use (clonePerson p = p { name = name p ++ " clone" }) constructor.

Method 1: Calling One Constructor from another by using user-defined function

In this method, we define a data type Person that has two fields, a name (String) and an age (Int). We then define a new constructor newPerson that takes a name and creates a new Person object with the age. We also define a printPerson function that takes a Person object and prints their name and age.

Algorithm

  • Step 1 − The data type ‘Person’ is defined with two fields name and an age.

  • Step 2 − The constructor is defined to create a new person object, as

  • newPerson name = Person name 10.

  • Step 3 − The printPerson function is defined as,

  • printPerson (Person name age) = putStrLn $ name ++ " is " ++ show age ++ " years old".

  • Step 4 − The program execution will be started from main function. The main() function has whole control of the program. It is written as main = do.

  • Step 5 − The variable named, ‘p1’ and ‘p2’ are defined that will call the ‘Person’ object and their details is printed. This is done when one constructor call the another constructor.

Example 1

In this example, the one constructor is called from the another by using user-defined function.

data Person = Person String Int

newPerson :: String -> Person
newPerson name = Person name 10

printPerson :: Person -> IO ()
printPerson (Person name age) = putStrLn $ name ++ " is " ++ show age ++ " years old"

main :: IO ()
main = do
  let p1 = Person "John" 30
      p2 = newPerson "Jane"
  printPerson p1
  printPerson p2

Output

[1 of 1] Compiling Main             ( main.hs, main.o )
Linking main ...
John is 30 years old
Jane is 10 years old

Example 2

In this example, a Person data type is defined with two fields name and age. It also defines two functions newPerson and clonePerson, which create a new person with the given name and age and create a clone of the given person with the name appended with " clone" respectively.

data Person = Person { name :: String, age :: Int } deriving (Show)

newPerson :: String -> Int -> Person
newPerson n a = Person { name = n, age = a }

clonePerson :: Person -> Person
clonePerson (Person n a) = Person { name = n ++ " clone", age = a }

main :: IO ()
main = do
  let person1 = newPerson "Alice" 25
      person2 = clonePerson person1
  putStrLn $ "Person 1: " ++ show person1
  putStrLn $ "Person 2: " ++ show person2

Output

[1 of 1] Compiling Main             ( main.hs, main.o )
Linking main ...
Person 1: Person {name = "Alice", age = 25}
Person 2: Person {name = "Alice clone", age = 25}

Example 3

In this example, we define the clonePerson function using record syntax to create a new Person object based on the given Person object p. We simply copy the age field and concatenate the string " clone" to the name field.

data Person = Person { name :: String, age :: Int } deriving (Show)

newPerson :: String -> Int -> Person
newPerson n a = Person { name = n, age = a }

clonePerson :: Person -> Person
clonePerson p = p { name = name p ++ " clone" }

main :: IO ()
main = do
  let person1 = newPerson "Alice" 25
      person2 = clonePerson person1
  putStrLn $ "Person 1: " ++ show person1
  putStrLn $ "Person 2: " ++ show person2

Output

[1 of 1] Compiling Main             ( main.hs, main.o )
Linking main ...
Person 1: Person {name = "Alice", age = 25}
Person 2: Person {name = "Alice clone", age = 25}

Example 4

In this example, we use record syntax to define the Person data type and a function clonePerson that takes a Person and returns a new Person with the same properties but with the name suffixed with " clone".

data Person = Person { name :: String, age :: Int } deriving (Show)

clonePerson :: Person -> Person
clonePerson p = p { name = name p ++ " clone" }

main :: IO ()
main = do
  let person1 = Person { name = "Alice", age = 25 }
      person2 = clonePerson person1
  putStrLn $ "Person 1: " ++ show person1
  putStrLn $ "Person 2: " ++ show person2

Output

[1 of 1] Compiling Main             ( main.hs, main.o )
Linking main ...
Person 1: Person {name = "Alice", age = 25}
Person 2: Person {name = "Alice clone", age = 25}

Conclusion

In Haskell, a data type can have multiple constructors. One constructor can call another constructor by using the same name as the data type and pattern matching. This is called a record syntax, where a constructor can have named fields that correspond to the data type's attributes.

Updated on: 28-Mar-2023

154 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements