在Haskell中访问"默认节目"?

Wil*_*sem 7 haskell overriding typeclass

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

data Greek = Alpha | Beta | Gamma | Delta | Eta | Number Int
Run Code Online (Sandbox Code Playgroud)

现在可以Show通过附加deriving Show该指令使其成为一个实例.

然而,我们希望表现Number Int为:

instance Show Greek where
    show (Number x) = show x
    -- ...
Run Code Online (Sandbox Code Playgroud)

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

    show Alpha = "Alpha"
    show Beta = "Beta"
Run Code Online (Sandbox Code Playgroud)

对于这个小例子,当然可行.但是如果选项的数量很长,则需要大量的工作.

我想知道是否可以访问"默认show"实现并使用通配符调用它.例如:

instance Show Greek where
    show (Number x) = show x
    show x = defaultShow x
Run Code Online (Sandbox Code Playgroud)

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

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

小智 7

不,那是不可能的AFAIK.

此外,自定义的情况下,Show应该有一个第二个想法,因为ShowRead实例应相互兼容.

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

假设您有一个Presentable带有方法的类型类present,以及默认Show实例,您可以编写:

instance Presentable Greek where
    present (Number x) = show x
    present x = show x
Run Code Online (Sandbox Code Playgroud)


dan*_*nem 7

您可以使用Data和Typeable来完成此操作.当然这是一个hack,这个例子只适用于你的例子中的"枚举"类型.

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

{-# 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
Run Code Online (Sandbox Code Playgroud)

我实现它的这种方法无法处理嵌套数据结构或任何其他远程花哨的东西,但同样,这是一个丑陋的黑客.如果你真的必须使用这种方法,你可以在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)
Run Code Online (Sandbox Code Playgroud)

  • 我认为你可以使用[generic-deriving](http://hackage.haskell.org/package/generic-deriving-1.7.0/docs/Generics-Deriving-Show.html)实现与第一个变体类似的东西,它可能也会处理嵌套的东西(只要一切都是`Generic`). (3认同)

pal*_*luh 7

正如@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
Run Code Online (Sandbox Code Playgroud)