我想写isShowable
作为此代码的一部分运行。
data MaybeShowable = forall a . Show a => Showable a | Opaque
f :: (Data d) => d -> String
f x = case isShowable x of
Showable s -> show s
Opaque -> "<<OPAQUE>>"
isShowable :: (Data d) => d -> MaybeShowable
isShowable = ???
这可以通过使用 Data
实现吗?实例?如果不是,最好的方法是什么?
注意:如果没有其他选择,我愿意接受这个版本,该版本仅适用于通过导入模块可见的类型类实例,其中 isShowable
已定义。
最佳答案
我不确定你的真实意图是什么,但看起来你想将 Java idiom 嵌入到 Haskell 中。
如前所述in other SO question你正在做的事情将变成反模式。
您已添加说明:
If I would be willing to settle for "typeclass instances visible through the imports to the module in which
isShowable
is defined".
你为什么不把你的类型包装在:
data MaybeShowable a where
Showable :: forall b. Show b => b -> MaybeShowable b
Opaque :: forall b. b -> MaybeShowable b
instance Show (MaybeShowable a) where
show (Showable x) = show x
show (Opaque x) = "<<OPAQUE>>"
并让您的函数在 MaybeShowable a
上运行,而不是在普通的 a
上运行。
但这仍然很丑陋。直接在Show a => a
,或者a
上操作是不是更简单。
其他方法是尽早捕获Show a
字典,即具有数据类型:
data MaybeShowable a = Showable a String -- Or even Showable a (a -> String)
| Opaque a
instance Show (MaybeShowable a) where
show (Showable x s) = s
show (Opaque x) = "<<OPAQUE>>"
wrapShow :: Show a => a -> MaybeShowable a
wrapShow x = Showable x (show x) -- Showable x show
wrapOpaque :: a -> MaybeShowable a
wrapOpaque = Opaque
这种方法的变体用于例如QuickCheck's forAll
.那部分是Haskell98。 show x
被关闭到闭包中,它可能被执行也可能不被执行。懒惰是这里的关键!
关于haskell - 一般地找出值的类型是否属于类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28194340/