代码如下所示:
class MyAnd a where
myAnd :: (Show a) => a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)
data TrafficLight = Red | Yellow | Green deriving(Show, MyAnd)
此处MyAnd
是一个具有函数myAnd
的类型类,我认为它是通用的,唯一的约束是a
必须有一个Show
的实例类..
在TrafficLight
类型中,它已派生自Show
类型类。但是,当我编译代码时,编译器会抱怨
Can't make a derived instance of ‘MyAnd TrafficLight’:
‘MyAnd’ is not a derivable class
In the data declaration for ‘TrafficLight’
Failed, modules loaded: none.
有没有人有这方面的想法?
答案 0 :(得分:9)
您不能使用用户定义的类派生。通常deriving
会自动为给定类的方法生成代码,这是唯一可能的,因为编译器知道这些方法应该做什么,因此可以根据类型的结构生成合适的实现。对于用户定义的类,这显然是不可能的,因为编译器无法知道方法应该如何表现。
在你的情况下,看起来你想要的只是使用你的类所拥有的一个方法的默认实现,因此编译器不需要生成任何实现。当然,这意味着deriving
根本不是必需的,您只需使用没有正文的实例声明。
PS:如果你总是想要使用该方法的默认实现,那么最好不要使用类,而只需将myAnd
定义为函数。
答案 1 :(得分:8)
对于此特定问题,您可以简单地避免定义自定义类:
data TrafficLight = Red | Yellow | Green deriving Show
myAnd :: (Show a) => a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)
现在,myAnd
适用于TrafficLight
(以及所有其他Show
种类型。)
答案 2 :(得分:0)
在试图弄清楚如何使用GHC的DeriveAnyClass
扩展名时发现了这个问题,该扩展名被问到才三周。
使用它,以下功能将达到您的期望:
{-# LANGUAGE DeriveAnyClass #-}
class Show a => MyAnd a where
myAnd :: a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)
data TrafficLight = Red | Yellow | Green deriving (Show, MyAnd)
但是应谨慎使用,因为它将字面派生 any 类,并在必要时创建空实例。