Access to "default display" in Haskell?

Say you have a data structure (borrowed from this question ):

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

You can now make it an instance of Show by adding the deriving Show to this statement.

Say, however, we want to show Number Int as:

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

The problem is that you need to specify all the other parts of the Greek data, as well as:

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

For this small example, which, of course, is possible. But if the number of options is long, this requires a large amount of work.

I am wondering if it is possible to access the default implementation and call it with a wildcard. For instance:

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

Thus, you "implement" specific patterns that differ from the default approach, and the rest of the patterns are resolved by the "backup mechanism".

Something a bit like overriding a method with reference to super.method in object-oriented programming.

+6
source share
3 answers

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

I am sure that we will be able to understand in more detail how we do it, but to cover your 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 implemented it, cannot handle nested data structures or something even more distant, but again, it's an ugly hack. If you really should use this approach, you can delve into the Data.Data package, I'm sure you could put something together ...

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

The correct way to do this is to use the newtype wrapper. I understand that this is not the most convenient solution, although, especially when using GHCi, but it does not incur additional overhead and it is less likely that an unexpected path will unexpectedly arise 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) 
+7
source

No, this is impossible AFAIK.

In addition, custom Show instances deserve a second thought, because Show and Read instances must be mutually compatible.

For simple conversion to human (or anyone) readable strings, use your own function or your own class. It will also provide what you want:

Assuming you have a Presentable typeclass with a present method, as well as a default Show instance, you could write:

 instance Presentable Greek where present (Number x) = show x present x = show x 
+7
source

As pointed out by @phg in the comment above, this can also be done using 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 
+6
source

Source: https://habr.com/ru/post/982868/


All Articles