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

时间:2015-05-17 14:49:37

标签: 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的实例类..

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.

有没有人有这方面的想法?

3 个答案:

答案 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 类,并在必要时创建空实例。