如何“显示”不可显示的类型?

我正在使用data-reify并将graphvizeDSL 转换为一个很好的图形表示,用于内省。

作为一个简单的、人为的例子,请考虑:

{-# LANGUAGE GADTs #-}

data Expr a where
  Constant :: a -> Expr a
  Map :: (other -> a) -> Expr a -> Expr a
  Apply :: Expr (other -> a) -> Expr a -> Expr a

instance Functor Expr where
  fmap fun val = Map fun val

instance Applicative Expr where
  fun_expr <*> data_expr = Apply fun_expr data_expr
  pure val = Constant val

-- And then some functions to optimize an Expr AST, evaluate Exprs, etc.

为了使内省更好,我想打印存储在 DSL 数据类型的某些 AST 节点内的值。但是,通常任何a可能存储在 中Constant,即使那些没有实现Show. 这不一定是一个问题,因为我们可以限制Expr像这样的实例:

instance Show a => Show (Expr a) where
  ...

然而,这不是我想要的:我仍然希望能够打印,Expr即使a不是Show-able,通过打印一些占位符值(例如只是它的类型和它不可打印的消息)。

因此,如果我们有一个aimplementation Show,我们想要做一件事,如果一个特定的a没有,则另一件事。

此外,DSL 也有构造函数MapApply这甚至更成问题。构造函数在 中是存在的other,因此我们不能对other,a或 做任何假设(other -> a)。添加约束类型otherMapRESP。Apply构造函数会破坏Functorresp的实现。Applicative转发给他们。

但在这里我也想打印这些功能:

  • 一个独特的参考。这始终是可能的(即使它是不漂亮,因为它需要unsafePerformIO使用)System.Mem.StableName
  • 它的类型,如果可能的话(一个技术是使用show (typeOf fun),但它要求funTypeable)。

我们再次遇到了一个问题,如果我们有一个f实施,我们想做一件事,如果没有Typeable,另一件事f

这该怎么做?


额外免责声明:这里的目标不是为Show不支持它的类型创建“正确”的实例。没有愿望Read以后能够他们,或者print a != print b暗示a != b

目标是以“适合人类内省”的方式打印任何数据结构。

我被困在的部分是,如果额外的约束对aresp持有,我想使用一种实现。(other -> a),但如果这些不存在,则为“默认”。也许FlexibleInstances这里需要类型类,或者类型族?我一直无法弄清楚(也许我一起走错了轨道)。

以上是如何“显示”不可显示的类型?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>