【问题标题】:Deriving instances with TypeFamilies使用 TypeFamilies 派生实例
【发布时间】:2012-10-20 03:09:42
【问题描述】:

我有一个类型类 Foo 与关联类型:

{-# LANGUAGE TypeFamilies #-}

class Foo a where
    type Bar a
    foo :: a -> Bar a

现在我想定义一个数据类型来保存其中一种关联类型,并为其派生一个Show 实例:

data Baz a = Baz (Bar a) deriving (Show)

不过,这并不能编译,因为您不能保证 Bar a 有一个 Show 实例

No instance for (Show (Bar a))
  arising from the 'deriving' clause of a data type declaration

我可以通过打开FlexibleContextsUndecidableInstances并手动编写Show实例来解决这个问题

{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}

data Baz a = Bar a

instance (Show a, Show (Bar a)) => Show (Baz a) where
    showsPrec _ (Baz x) = showString "Baz " . shows x

但这并不是特别令人满意,尤其是当Baz 比一个值的简单包装器更复杂时,或者当我还想派生其他类型类的实例时。有出路吗?

【问题讨论】:

    标签: haskell types type-families


    【解决方案1】:

    您可以使用StandaloneDeriving 要求GHC 生成与以往相同的Show 实例,但具有不同的上下文:

    {-# LANGUAGE FlexibleContexts, StandaloneDeriving, TypeFamilies, UndecidableInstances #-}
    
    class Foo a where
        type Bar a
        foo :: a -> Bar a
    
    data Baz a = Baz (Bar a)
    deriving instance Show (Bar a) => Show (Baz a)
    

    【讨论】:

    • 编译器不能自动添加Show (Bar a) 上下文是否有理论上的原因?比如你的数据类型是data Baz a = Baz a,那么编译器就可以自动添加Show a,就不需要独立推导了。
    • @MikeIzbicki 我不认为有理论上的原因它不能,不。也许 Haskell 提出的类似 deriving instance of Show Bar 的提议确实与非独立版本的派生完全一样。
    猜你喜欢
    • 1970-01-01
    • 2020-04-07
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2023-02-22
    • 1970-01-01
    • 2021-11-16
    相关资源
    最近更新 更多