如何创建StandaloneDeriving实例

时间:2017-01-30 15:13:45

标签: haskell derived-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))

1 个答案:

答案 0 :(得分:3)

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

这意味着a应该被类型构造函数替换。例如,LineItem Maybe是良好的,但LineItem (Maybe Int)不是。

最通用的Show实例就像是

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

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

请注意,由于此实例不会简化"头部受到较小的约束,有可能通过进一步添加“坏”和“#34;我们可以使编译器永远循环的实例。在实践中,这很少发生,我不会过分担心它。

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

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