Haskell中的“Subclassing”节目?

时间:2010-03-27 14:44:42

标签: haskell types typeclass

假设我有以下内容:

data Greek = Alpha | Beta | Gamma | Phi deriving Show

我想使用除Beta以外的所有项目的默认显示,我想说“两个”。

我可以这样做吗?

4 个答案:

答案 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)

据我所知,你不能。无论如何,派生机制都不支持更改或扩展派生实例。