使用更高级类型的变量派生

Deriving with higher-kinder type variables

假设我有一个多态类型,其中一个参数是更高种类的类型 (* -> *)。

data Tricky m = Tricky { numbers :: m Int, genesis :: m String }

是否有一种通用的方法可以在不使用神秘和不安全的语言扩展的情况下为此类类型派生实例?

我尝试启用 StandaloneDeriving 以便我可以指定上下文:

deriving instance Show (m Int) => Show (Tricky m)

但是 GHC 然后抱怨约束不小于实例头,并指出我 UndecidableInstances 的方向。

总结一下:

1.我应该简单地接受这个建议,还是有更好的方法?

2.有没有什么建议可以简化这个过程?

3. 想要派生 'higher-kinded' 个实例是不是有些错误?为一些具体类型派生实例会更好吗(例如 Vector[]Set

1. UndecidableInstances.

没有什么不安全的地方

还有一种定义Show (Tricky m)的方法,就是要求m满足forall a. Show a => Show (m a)。这是由

这样的类型类捕获的
class Show1 f where
    showsPrec1 :: Show a => Int -> f a -> ShowS

基础 4.9 中添加了 even cleverer version of Show1。它更通用,因为它可用于在 a 没有 Show a 实例时显示 m a

2.您已经找到了执行此操作的正确点点滴滴。

3. 不,它是正确的,可以抽象出甚至更高级的结构,如 Vector[]Set . Monad 转换器具有种类 (* -> *) -> (* -> *) 和种类 (* -> *) 的抽象类型,与仿函数相同,以生成与仿函数相同种类的类型。 Tricky 具有种类 (* -> *) -> *,它采用与仿函数相同种类的东西并生成普通数据类型。我称这种数据类型为 "Models",因为它们产生了一种数据类型,抽象了它是如何组合在一起的。