【问题标题】:Guarantee that type families will derive certain classes保证类型族将派生某些类
【发布时间】:2012-09-13 18:35:00
【问题描述】:

我有类似以下的内容:

{-# LANGUAGE TypeFamilies #-}

class Configuration c where
    data Pig c
    data Cow c

    parsePig :: GenParser Char st (Pig c)
    parseCow :: GenParser Char st (Cow c)

data Farm c =
    { pigs :: [Pig c]
    , cows :: [Cow c]
    } deriving Show

由于deriving Show 行而失败。我不知道如何强制所有Configuration 实例确保它们的data Pigdata Cow 实现都是Show 的实例。

我知道我可以让它有 showPigshowCow 方法并写出整个复杂的 show 实例,但实际上事情比这更复杂,那会很痛苦。

是否有一种简单、优雅的方式来保证类型族实例本身就是某些类的实例?

【问题讨论】:

  • 它不会因为LANGAUGE 行而失败?
  • 这不是整个文件;为了这个问题,我把它删减了。显然有一个模块声明、一个 ParserCombinators.Parsec 导入等等。
  • 我认为马特的意思是该行声明 LANGAUGE 而它应该是 LANGUAGE

标签: haskell type-families


【解决方案1】:

您可以使用StandaloneDerivingShow 实例手动指定约束。

{-# LANGUAGE StandaloneDeriving, FlexibleContexts, UndecidableInstances #-}
deriving instance (Show (Pig c), Show (Cow c)) => Show (Farm c)

这仍然可以让您拥有CowPigConfiguration 实例,但它们不实现Show,但是,只要您不尝试show 它们。

【讨论】:

    【解决方案2】:

    既然你说你想强制Configuration的所有实例让Pig cCow c实现Show,一个更简单的方法是简单地限制类型类上下文中的家庭,如下所示:

    {-# LANGUAGE TypeFamilies, FlexibleContexts #-}
    
    class (Show (Pig c), Show (Cow c)) => Configuration c where
        data Pig c
        data Cow c
    
    data Farm c = Farm { pigs :: [Pig c],
                         cows :: [Cow c] } deriving (Show)
    

    编辑:

    正如@hammar 在他的评论中指出的那样,前面的代码不会编译。正如他所建议的,解决此问题的一种方法是使用StandaloneDeriving。另一种方式是这样的:

    {-# LANGUAGE TypeFamilies, FlexibleContexts, GADTSyntax #-}
    
    class (Show (Pig c), Show (Cow c)) => Configuration c where
        data Pig c
        data Cow c
    
    data Farm c where
        Farm :: Configuration c => { pigs :: [Pig c],
                                     cows :: [Cow c] } -> Farm c deriving (Show)
    

    这两种方法的结果略有不同,如果您调用 show,@hammar 的方法将需要Configuration 约束,而我的方法将提供 > 表示约束。

    【讨论】:

    • 这不能编译(至少使用 GHC 7.4.1)。但是,将此方法与使用 deriving instance Configuration c => Show (Farm c)StandaloneDeriving 方法相结合,就无需使用 UndecidableInstances
    猜你喜欢
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多