haskell - 一般地找出值的类型是否属于类型类

标签 haskell reflection typeclass

我想写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/

相关文章:

haskell - 为什么 Haskell 会递归导入实例?为什么不只从指定模块导入所有实例?

Haskell concat Int

c# - 无法将类型为 'System.Object[]' 的对象转换为 'MyObject[]',这是怎么回事?

haskell - 重叠多参数实例和实例特异性

haskell - 在 Haskell 中将两个类合并/合并为一个类

haskell - 有没有用于集成复杂功能的 Haskell 库?

haskell - 模式匹配与构造函数

c# - 传递用于访问属性的 Lambda 表达式列表

c# - 如何通过反射调用带有枚举(enum)参数的方法?

haskell - 如何为某些类型创建专门的类型类,为其余类型创建默认实现