I'm trying to define my own Show
class named MyShow
, and want to 'steal' instances from TextShow
and Prelude.Show
, and prefer the former one if both exists.
I tried following (showbPrec
things is simplified to be focused):
{-# LANGUAGE UndecidableInstances #-}
import Data.Text (Text, pack, unpack)
import qualified Prelude as P
import qualified TextShow as T
class MyShow a where
showText :: a -> Text
instance {-# OVERLAPPING #-} TextShow a => MyShow a where
showText x = T.showt x
instance {-# OVERLAPPABLE #-} P.Show a => MyShow a where
showText x = pack (P.show x)
But I'm telled that Duplicate instance declarations is not allowed, so is there any way to define my own Show
and reuse instances from others?
CodePudding user response:
This won't let you branch on which instance is available, that goes against the open-world assumption where adding a new instance should not change the behaviour of your program. There are ways of doing this kind of branching, one approach is the compiler plugin IfSat
but this is not the normal way of doing it.
newtype AsShow a = AsShow a
instance P.Show a => MyShow (AsShow a) where
showText :: AsShow a -> Text
showText (AsShow a) = pack (P.show a)
newtype AsTextShow a = AsTextShow a
instance TextShow a => MyShow (AsTextShow a) where
showText :: AsTextShow a -> Text
showText (AsTextShow a) = showt a
With these newtypes you can then derive instances for your MyShow
using DerivingVia
{-# Language DerivingVia #-}
{-# Language StandaloneDeriving #-}
-- standalone deriving for types defined elsewhere
deriving via AsShow Int instance MyShow Int
deriving via AsShow Integer instance MyShow Integer
data BOOL = FALSE | TRUE
deriving
stock P.Show
deriving MyShow
via AsShow BOOL