0

Apart from instance IsPerson (EmployeeRecord a) the whole code is a part of the post General Functions with Typeclasses.

ghci compiles the code, but printPerson doesn't print anything. I guess it calls itself recursively.

Main> :l type-class.hs 
[1 of 1] Compiling Main             ( type-class.hs, interpreted )
Ok, modules loaded: Main.
*Main> printPerson $ EmployeeRecord (Student "me" 123) 11

Removing of instance IsPerson (EmployeeRecord a) leads to the exception

Main> printPerson $ EmployeeRecord (Student "me" 123) 11

<interactive>:116:1: error:
    * No instance for (IsPerson (EmployeeRecord Student))
        arising from a use of `printPerson'
    * In the expression:
        printPerson $ EmployeeRecord (Student "me" 123) 11
      In an equation for `it':
          it = printPerson $ EmployeeRecord (Student "me" 123) 11

How should instance IsPerson EmployeeRecord be implemented solve the issue with printPerson?

data Student = Student String Int deriving Show

data Teacher = Teacher
  { teacherName:: String
  , teacherAge:: Int
  , teacherDepartment :: String
  , teacherSalary :: Int
  } deriving Show

class IsPerson a where
  personName :: a -> String
  personAge :: a -> Int

instance IsPerson Student where
  personName (Student n _) = n
  personAge (Student _ a) = a

instance IsPerson Teacher where
  personName = teacherName
  personAge  = teacherAge

data (IsPerson a) => EmployeeRecord a = EmployeeRecord
  {
      employe :: a
    , tenure :: Int
  } deriving (Show)


instance IsPerson (EmployeeRecord a) where
  personName a = personName a
  personAge = undefined

printPerson :: (IsPerson a) => a -> IO ()
printPerson p = putStrLn $ personName p
1
  • thanks @4castle. It solves the issue, if instance defination is replaced by instance (IsPerson a) => IsPerson (EmployeeRecord a) where Commented Jan 1, 2018 at 19:46

1 Answer 1

4

Your EmployeeRecord type is like a "box" where the type implementing IsPerson is inside. You need to "unbox" the EmployeeRecord in order to access the "inner" personName.

You can do this unboxing by either pattern matching or using the employe function.

instance IsPerson (EmployeeRecord a) where
  personName (EmployeeRecord a _) = personName a
  personAge (EmployeeRecord a _) = personAge a
instance IsPerson (EmployeeRecord a) where
  personName = personName . employe
  personAge = personAge . employe

By the way, your code makes use of the deprecated DatatypeContexts language extension. Rather than put the constraint on a in the EmployeeRecord type declaration, put the constraint in your instance declaration:

instance IsPerson a => IsPerson (EmployeeRecord a) where
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.