【问题标题】:Derived instance in HaskellHaskell 中的派生实例
【发布时间】:2017-09-04 06:39:13
【问题描述】:

我想像这样使用派生实例:

data Test3D = forall a. (Show a, Eq a, Typeable a, Generic a)
                => Test3D { testDt :: String
                          , testPrm :: a
                          }
   deriving (Show, Eq, Typeable, Generic)

instance Binary (Test3D)
$(deriveJSON defaultOptions ''Test3D)

但我从 GHC 收到:

• Can't make a derived instance of ‘Show Test3D’:
        Constructor ‘Test3D’ has existentials or constraints in its type
        Possible fix: use a standalone deriving declaration instead
• In the data declaration for ‘Test3D’

这种方式对我的项目来说非常方便。我找不到解决办法。

有什么方法可以为这些数据使用派生实例吗?

【问题讨论】:

  • 如何自己编写实例?如果您想显示有关testPrm 的任何信息,即使写出类型签名也很困难。如果你不知道怎么做,那么 GHC 就不能自动为你做。另一方面,如果您不关心显示testPrm,那么实例很容易手动编写,您不需要派生它。
  • 这涉及为每个Generic 编写一个Binary 实例。它看起来是一项相当复杂的任务。我认为我们不能现实地希望自动派生机制为我们解决了这个问题。如果我们使用Binary a 而不是Generic a,也许我们可以手动编写一个更简单的实例?
  • 也许我没有正确实现我的想法。我只想拥有某种类型的数据,而这些数据又包含一个未知类型的字段。但是字段类型通过类型类满足一定的要求。所有这些都应该是(Show a, Eq a, Typeable a, Generic, ...)。

标签: haskell deriving


【解决方案1】:

有什么方法可以为这些数据使用派生实例吗?

是的。按照 GHC 的建议做,制作一个独立派生子句:

{-# LANGUAGE StandaloneDeriving, ExistentialQuantification #-}

data Test3D = forall a. (Show a)
                => Test3D { testDt :: String
                          , testPrm :: a
                          }

deriving instance Show Test3D

您不能做的是派生Eq 实例,因为不同的值实际上可能包含不同的类型,并且只能通过Typeable 将这些与动态转换黑客进行比较。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    相关资源
    最近更新 更多