假设我有以下内容:
data Greek = Alpha | Beta | Gamma | Phi deriving Show
我想使用除Beta以外的所有项目的默认显示,我想说“两个”。
我可以这样做吗?
答案 0 :(得分:17)
deriving Show
使用标准实例化机制(简单地返回定义)。如果你想要任何特殊的东西,你必须手动实例化它:
data Greek = Alpha | Beta | Gamma | Phi
instance Show Greek
where
show Alpha = "Alpha"
show Beta = "2"
show Gamma = "Gamma"
show Phi = "Phi"
答案 1 :(得分:7)
这并不完全令人满意,但你可以做到:
data Greek = Alpha | Beta | Gamma | Phi
deriving (Show)
showGreek Beta = "2"
showGreek x = show x
并使用showGreek而不是show。如果你需要一个真正的展示实例(在我的代码中我发现我需要这个比初学者倾向于认为的要少),你可以做相当麻烦的事情:
newtype Greek' = Greek' Greek
instance Show Greek' where
show (Greek' g) = showGreek g
如果是我的代码,我会坚持使用showGreek
。
我使用的一个不错的经验法则是Show和Read实例仅由Haskell生成。如果show不生成有效的Haskell代码,则它不应该在Show实例中。
答案 2 :(得分:4)
其他一些建议在您的特定示例中效果很好,我建议您使用这些建议。
但在更一般的情况下,您可能希望使用datatype-generic programming。
使用泛型编程,您可以编写适用于多种数据类型的函数,即对每种数据类型执行相同操作的函数。这些函数的例子是show
和==
(这就是GHC中可以推导出这些函数的原因)。
这是使用regular库的示例:
{-# LANGUAGE TemplateHaskell, EmptyDataDecls, TypeFamilies #-}
import Generics.Regular
import qualified Generics.Regular.Functions.Show as G
data Greek = Alpha | Beta | Gamma | Phi
-- These two lines are all that is needed to use
-- Regulars generic functions on the 'Greek' data type.
$(deriveAll ''Greek "PFGreek")
type instance PF Greek = PFGreek
-- Manual written instance for 'Show'
instance Show Greek where
show Beta = "Two"
show x = G.show x -- Use Regulars 'show' for the boring parts
老实说,我真的不喜欢Regulars show
函数的输出(它会抛出一组额外的括号)。但这可能是编写自己的通用函数的一个很好的起点。
答案 3 :(得分:3)
据我所知,你不能。无论如何,派生机制都不支持更改或扩展派生实例。