假设我有一个多态类型,其中一个参数是更高级的类型(* -> *
)。
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
)
答案 0 :(得分:8)
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
。它更为通用,因为它可用于在m a
没有a
实例时显示Show a
。
2。你找到了正确的点点滴滴。
3。不,对于Vector
,[]
和Set
等更高级别的结构,它是正确的。 Monad变换器具有类型(* -> *) -> (* -> *)
和抽象类型(* -> *)
,与仿函数类似,用于生成与仿函数相同类型的类型。 Tricky
具有(* -> *) -> *
种类,它与仿函数具有相同的类型并生成普通数据类型。我称之为“模型”的数据类型,因为它们产生了一个数据类型,抽象了它是如何组合在一起的。