如何创建 StandaloneDeriving 实例

How to create StandaloneDeriving instances

给定以下代码

{-# LANGUAGE StandaloneDeriving  #-}

type Date = Int
data Decision a = Decision a deriving (Show)  

data InProgress a = InProgress {progress :: a, decision :: Decision a } deriving (Show)
data Finished a = Finished {finished :: a, initial :: a, timestamp :: Date } deriving (Show)  

data LineItem a = LineItem {article :: a String, amount :: a Float, units :: a Int } deriving (Show)  

我收到以下错误

source_file.hs:11:96:
    No instance for (Show (a Float))
    arising from the second field of ‘LineItem’ (type ‘a Float’)
    Possible fix:
    use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Show (LineItem a))

我尝试了下面这样的一些变体 - 但我无法理解 运行。

deriving instance Show a => Show (InProgress Float)

我该如何解决这个问题? (非常感谢一些解释)

编辑

好的,我有办法

deriving instance Show (LineItem InProgress)

会做我想做的。我还是不明白为什么不是

deriving instance Show a => Show (LineItem (InProgress a))

aLineItem a 不是类型,即它没有种类 *。 相反,它有种类 * -> *.

这意味着 a 有望被类型构造函数替换。例如,LineItem Maybe 是 well-kinded,但 LineItem (Maybe Int) 不是。

最一般的 Show 实例类似于

deriving instance (Show (a String), Show (a Int), Show (a Float)) 
                  => Show (LineItem a)

但是上下文涉及比头部更复杂的类型。这肯定需要打开 UndecidableInstances 和可能的其他一些扩展。

请注意,由于此实例不会 "simplify" 进入更小的约束,因此通过添加更多 "bad" 实例,我们有可能使编译器永远循环。实际上,这种情况很少发生,我不会太担心。

如果您知道 a 在后续使用中只有有限数量的案例,您可以一一列出,为每个案例提供一个实例,就像您在编辑中所做的那样。

deriving instance Show (LineItem TyCon1)
...
deriving instance Show (LineItem TyConN)