Accessing the “default show” in Haskell?

痴心易碎 提交于 2019-11-29 06:58:58

You can sorta accomplish this using Data and Typeable. It is a hack of course, and this example only works for "enumerated" types as in your example.

I'm sure we could get more elaborate with how we do this, but to cover your given example:

{-# 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

This approach as I've implemented it cannot handle nested data structures or anything else remotely fancy, but again, this is an ugly hack. If you really must use this approach you can dig around in the Data.Data package I'm sure you could piece something together...

Here is a blog post giving a quick introduction to the packages: http://chrisdone.com/posts/data-typeable

The proper way to go about this would be to use a newtype wrapper. I realize that this isn't the most convenient solution though, especially when using GHCi, but it incurs no additional overhead, and is less likely to break in unexpected ways as your program grows.

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)

No, that's not possible AFAIK.

Further, custom instances of Show deserve a second thought, because Show and Read instances should be mutually compatible.

For just converting to human (or whoever) readable strings, use your own function or own typeclass. This will also achieve what you want:

Assuming you have a Presentable typeclass with a method present, and also the default Show instance, you can write:

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

As @phg pointed above in comment this can be also done with help of generic-deriving:

{-# 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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!