我正在尝试定义自己的Show名为 的类MyShow,并希望从TextShow 和 中“窃取”实例Prelude.Show,并且如果两者都存在,则更喜欢前一个。
我尝试了以下操作(showbPrec事情被简化以集中精力):
{-# 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)
Run Code Online (Sandbox Code Playgroud)
但我被告知不允许重复实例声明Show,那么有什么方法可以定义我自己的实例并重用其他人的实例吗?
这不会让您分支到哪个实例可用,这违背了开放世界的假设,即添加新实例不应改变程序的行为。有多种方法可以进行这种分支,一种方法是编译器插件IfSat,但这不是正常的方法。
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
Run Code Online (Sandbox Code Playgroud)
使用这些新类型,您可以派生实例以供您MyShow使用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
Run Code Online (Sandbox Code Playgroud)