使用更高级的类型变量派生
Posted
技术标签:
【中文标题】使用更高级的类型变量派生【英文标题】:Deriving with higher-kinder type variables 【发布时间】:2016-09-30 16:55:23 【问题描述】:假设我有一个多态类型,其中一个参数是更高种类的类型 (* -> *
)。
data Tricky m = Tricky numbers :: m Int, genesis :: m String
是否有一种通用方法可以在不使用神秘和不安全的语言扩展的情况下为此类类型派生实例?
我尝试启用 StandaloneDeriving
以便我可以指定上下文:
deriving instance Show (m Int) => Show (Tricky m)
但是 GHC 然后抱怨约束不小于实例头,并将我指向UndecidableInstances
的方向。
总结一下:
1.我应该简单地接受这个建议,还是有更好的方法?
2.是否有任何建议可以简化此过程?
3. 想要派生“更高种类”的实例是不是有点错误?为一些具体类型派生实例会更好吗(例如Vector
、[]
、Set
)
【问题讨论】:
【参考方案1】:1.UndecidableInstances
没有什么不安全的地方。
还有另一种定义Show (Tricky m)
的方法,即要求m
满足forall a. Show a => Show (m a)
。这是由像
class Show1 f where
showsPrec1 :: Show a => Int -> f a -> ShowS
even cleverer version of Show1
已添加到基础 4.9。它更通用,因为当a
没有Show a
实例时,它可用于显示m a
。
2.您已经找到了正确的方法。
3. 不,对更高级的结构进行抽象是正确的,例如Vector
、[]
和Set
。 Monad 转换器有(* -> *) -> (* -> *)
类型和抽象类型(* -> *)
,与函子相同,以产生与函子相同类型的类型。 Tricky
有一种(* -> *) -> *
,它接受与函子同种的东西并产生一个普通的数据类型。我将这种数据类型称为“模型”,因为它们产生了一种数据类型,抽象了它是如何组合在一起的。
【讨论】:
以上是关于使用更高级的类型变量派生的主要内容,如果未能解决你的问题,请参考以下文章
go语言学习笔记 — 基础 — 高级数据类型 — 派生类型:指针(pointer)数据容器函数(func)结构体(struct)通道(channel)