Haskell 确保类型族将派生某些类
我有如下几点:Haskell 确保类型族将派生某些类,haskell,type-families,Haskell,Type Families,我有如下几点: {-# 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] } der
{-# 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
由于派生显示
行,此操作失败。我不知道如何强制所有配置
实例以确保它们的数据清管器
和数据奶牛
实现都是显示
的实例
我知道我可以让它有showPig
和showCow
方法,并写出整个复杂的show
实例,但事实上事情比这更复杂,这将是一个相当痛苦的过程
是否有一种简单、优雅的方法来保证类型族实例本身就是某些类的实例?您可以使用
独立派生
手动指定约束,仅用于显示
实例
{-# LANGUAGE StandaloneDeriving, FlexibleContexts, UndecidableInstances #-}
deriving instance (Show (Pig c), Show (Cow c)) => Show (Farm c)
这仍然会让您拥有
配置
实例,其中Cow
和Pig
未实现显示
,但是,只要您不尝试显示
既然您说过要强制所有配置
的实例使用Pig c
和Cow c
实现显示
,那么更简单的方法就是在类的上下文中简单地约束类型族,如下所示:
{-# 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在他的评论中指出的,前面的代码不会编译。解决这一问题的一种方法是按照他的建议,使用独立派生。另一种方式是:
{-# 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的方法将需要配置
约束,而我的方法将提供所述约束。它不会因为LANGAUGE
行而失败?这不是整个文件;为了这个问题,我把它删减了。显然有一个模块声明,一个ParserCombinators.Parsec import,等等。我认为Matt的意思是,行状态为LANGAUGE
,而它应该是LANGUAGE
。这不会编译(至少使用GHC 7.4.1)。但是,使用派生实例配置c=>Show(farmc)
将其与标准派生方法相结合,可以避免使用不可判定实例。