类实例实现

时间:2018-01-01 19:26:16

标签: haskell

除了instance IsPerson (EmployeeRecord a)之外,整个代码都是帖子General Functions with Typeclasses的一部分。

ghci编译代码,但printPerson不会打印任何内容。我想它会递归地调用它自己。

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

删除instance IsPerson (EmployeeRecord a)会导致异常

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

如何instance IsPerson EmployeeRecord实施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 个答案:

答案 0 :(得分:4)

您的EmployeeRecord类型就像一个“框”,其中实现IsPerson的类型在其中。您需要“取消装箱”EmployeeRecord才能访问“内部”personName

您可以通过模式匹配或使用employe功能进行拆箱。

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

顺便说一下,您的代码使用了已弃用的DatatypeContexts语言扩展。而不是将a约束放在EmployeeRecord类型声明中,而是将约束放在instance声明中:

instance IsPerson a => IsPerson (EmployeeRecord a) where