除了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
答案 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