在Haskell中,如何自动派生这样一个自定义类?

在Haskell中,如何自动派生这样一个自定义类?,haskell,functional-programming,Haskell,Functional Programming,代码如下所示: 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类的实例 在Tr

代码如下所示:

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
type中,它已经派生自
Show
type类。然而,当我编译代码时,编译器会抱怨

    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.

有人对此有想法吗?

您不能将派生用于用户定义的类。通常,
派生
会自动为给定类的方法生成代码,这是因为编译器知道这些方法应该做什么,因此可以根据类型的结构生成合适的实现。对于用户定义的类,这显然是不可能的,因为编译器无法知道这些方法应该如何运行

在您的例子中,您似乎只想使用类所拥有的一个方法的默认实现,因此不需要由编译器生成任何实现。当然,这意味着根本不需要
派生
,您可以只使用实例声明而不使用主体


PS:如果您总是希望使用该方法的默认实现,那么最好不要使用类,而只是将
myAnd
定义为函数。

对于这个特定问题,您可以简单地避免定义自定义类:

data TrafficLight = Red | Yellow | Green deriving Show

myAnd :: (Show a) => a -> a -> String
x `myAnd` y = (show x) ++ " and " ++ (show y)

现在,
myAnd
适用于
TrafficLight
s(以及所有其他
Show
able类型)。

在尝试了解如何使用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)

但是应该谨慎使用,因为它实际上会派生任何类,在必要时创建空实例。

True,编译器不知道这些方法应该做什么。但也许在语言中添加一个值得一提的内容是一种表达方式。相关的: