【问题标题】:Refactoring Haskell code重构 Haskell 代码
【发布时间】:2016-04-03 12:17:32
【问题描述】:

实例化类型类可以泛化吗?

我有以下几段 Haskell 代码:

data Variable = Var Char (Maybe Integer)
    deriving (Eq)
instance Show Variable where
    show (Var c Nothing) = [c]
    show (Var c (Just n)) = c : show n

data Funcsymb = FuncS Char (Maybe Integer)
    deriving (Eq)
instance Show Funcsymb where
    show (FuncS c Nothing) = [c]
    show (FuncS c (Just n)) = c : show n

data Relsymb = RelS Char (Maybe Integer)
    deriving (Eq)
instance Show Relsymb where
    show (RelS c Nothing) = [c]
    show (RelS c (Just n)) = c : show n

我可以不写这么多重复吗?我知道我可以对这三个都使用(Char, Maybe Integer),但我宁愿使用不同的类型。

【问题讨论】:

  • 如果你喜欢单独的类型,为什么不使用newtype
  • 你可以定义“showSym :: Char -> Maybe Integer -> String”。此外,您可能希望在文本输出中明确它是哪种类型。
  • @Zeta 我不确定newtype 在这里会如何提供帮助。我还是得写三个独立的instances,对吧?
  • @Veky 是的,但那些会像 show (MyWrapper a) = show a 一样微不足道(当然你可以在这里做同样的事情) - 如果你不需要覆盖任何其他简单的类型同义词可能没问题太
  • 嗯...所以我定义另一个(基本)类型,为它编写 show,然后使用它定义这三个?还是说我可以直接说instance Show (Char, Maybe Integer) where ... 而不定义新类型?

标签: haskell refactoring dry typeclass


【解决方案1】:

您可以使用一两个辅助函数来减少重复。

showIfJust :: (Show a) => Maybe a -> String
showIfJust (Just a) = show a
showIfJust _ = ""

showCharMaybe = (Show a) => Char -> Maybe a -> String
showCharMaybe c m = c : showIfJust m

data Variable = Var Char (Maybe Integer)
    deriving (Eq)

instance Show Variable where
    -- this can be written as
    -- c : showIfJust n
    -- or showCharMaybe c m
    show (Var c mn) = showCharMaybe c mn

data Funcsymb = FuncS Char (Maybe Integer)
    deriving (Eq)

instance Show Funcsymb where
    show (FuncS c mn) = showCharMaybe c mn

data Relsymb = RelS Char (Maybe Integer)
    deriving (Eq)

instance Show Relsymb where
    show (RelS c mn) = showCharMaybe c mn

此外,您可以将 data 声明切换为 newtype,因为它们都是单个构造函数声明。这是一个小的优化。 More details about newtype.

【讨论】:

    猜你喜欢
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多