访问哈斯克尔的"default show"?



假设您有一个数据结构(借用了这个问题):

data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int

现在,通过在该指令上附加deriving Show,可以使其成为Show的实例。

假设我们希望将Number Int显示为:

instance Show Greek where
    show (Number x) = show x
    -- ...

问题是必须指定Greek数据的所有其他部分,如:

    show Alpha = "Alpha"
    show Beta = "Beta"

对于这个小例子来说,这当然是可行的。但是,如果选择的数量很长,就需要大量的工作。

我想知道是否可以访问"默认显示"实现并使用通配符进行调用。例如:

instance Show Greek where
    show (Number x) = show x
    show x = defaultShow x

因此,您"实现"了与默认方法不同的特定模式,其余模式由"回退机制"解决。

有点类似于面向对象编程中引用super.method的方法重写。

正如上面评论中提到的@phg,这也可以在泛型派生的帮助下完成:

{-# LANGUAGE DeriveGeneric #-}
module Main where
import           Generics.Deriving.Base (Generic)
import           Generics.Deriving.Show (GShow, gshow)
data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int
  deriving (Generic)
instance GShow Greek
instance Show Greek where
  show (Number n) = "n:" ++ show n
  show l = gshow l
main :: IO ()
main = do
  print (Number 8)
  print Alpha

您可以使用Data和Typeable对其进行排序。当然,这是一个破解,这个例子只适用于你的例子中的"枚举"类型。

我相信我们可以更详细地说明我们是如何做到这一点的,但要涵盖你给出的例子:

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data
import Data.Typeable
data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int 
             deriving (Data,Typeable)
instance Show Greek where
    show Number n = show n
    show x = show $ toConstr x

正如我所实现的,这种方法无法处理嵌套的数据结构或任何其他奇特的东西,但同样,这是一个丑陋的破解。如果你真的必须使用这种方法,你可以在Data.Data包中四处挖掘,我相信你可以拼凑一些东西。。。

下面是一篇博客文章,简要介绍了这些软件包:http://chrisdone.com/posts/data-typeable

实现这一点的正确方法是使用newtype包装器。我意识到这不是最方便的解决方案,尤其是在使用GHCi时,但它不会产生额外的开销,而且随着程序的增长,它不太可能以意外的方式中断。

data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int 
         deriving (Show)
newtype SpecialPrint = SpecialPrint Greek
instance Show SpecialPrint where
    show (SpecialPrint (Number x)) = "Number: " ++ show x
    show (SpecialPrint x) = show x
main = do
    print (SpecialPrint Alpha)
    print (SpecialPrint $ Number 1)

不,这是不可能的AFAIK。

此外,Show的自定义实例值得重新考虑,因为ShowRead实例应该相互兼容。

要转换为人类(或任何人)可读的字符串,请使用您自己的函数或类型类。这也将实现您想要的:

假设您有一个方法为presentPresentable类型类,以及默认的Show实例,那么您可以编写:

instance Presentable Greek where
    present (Number x) = show x
    present x = show x

最新更新