假设我有一个多态类型,其中一个参数是更高级的类型( * -> *
)。
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. 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。它更通用,因为它可用于显示 m a
当a
没有 Show a
实例。2. 你已经找到了正确的点点滴滴。
3. 不,对更高级的结构(如
Vector
)进行抽象是正确的。 , []
, 和 Set
. Monad 变压器有那种 (* -> *) -> (* -> *)
和类型的抽象 (* -> *)
, 与仿函数同种类,产生与仿函数同种类的类型。 Tricky
有种(* -> *) -> *
,它需要一些与仿函数相同类型的东西并产生一个普通的数据类型。我称这种类型的数据类型为“模型”,因为它们产生的数据类型抽象了它是如何组合在一起的。
关于haskell - 使用更高级的类型变量派生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39796459/