【问题标题】:In Haskell, how to derive such a custom class automatically?在 Haskell 中,如何自动派生这样一个自定义类?
【发布时间】:2015-05-17 14:49:36
【问题描述】:

代码如下所示:

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.

有人对此有想法吗?

【问题讨论】:

    标签: haskell functional-programming


    【解决方案1】:

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

    在您的情况下,您似乎只想使用您的类具有的一种方法的默认实现,因此编译器不需要生成任何实现。当然,这意味着 deriving 根本没有必要,您可以只使用没有正文的实例声明。

    PS:如果您总是想使用该方法的默认实现,那么根本不使用类可能是最有意义的,而只需将myAnd 定义为一个函数。

    【讨论】:

    【解决方案2】:

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

    data TrafficLight = Red | Yellow | Green deriving Show
    
    myAnd :: (Show a) => a -> a -> String
    x `myAnd` y = (show x) ++ " and " ++ (show y)
    

    现在,myAnd 适用于 TrafficLights(以及所有其他 Showable 类型)。

    【讨论】:

      【解决方案3】:

      在尝试弄清楚如何使用 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)
      

      但应谨慎使用,因为它会从字面上派生 任何 类,并在必要时创建空实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多