如何为三元类型构造函数(ext3)定义SYB函数来扩展类型?

5
Scrap Your Boilerplate package中,在Data.Generics.Aliases中有函数允许对一元和二元类型构造函数进行类型扩展。特别地,定义了ext1ext2
现在,ext1ext2是通过dataCast1dataCast2来定义的,它们是Data类型类的一部分,并且通常由DeriveDataTypeable机制来定义。但是,没有dataCast3,所以我看不到定义ext3的简单方法。
是否可能定义ext3,如果可以,怎么做呢?

请注意,gcast1gcast2是存在的,但没有更高的版本。 - user824425
@Tinctorius 是的,定义gcast3很容易,但我认为在Data实例之外没有足够的类型信息来定义ext3以使用gcast3 - scvalex
1个回答

0

我非常确定这还不够。但感觉已经非常接近了。

ext3 :: (Data a, Typeable3 t)
     => c a
     -> (forall d1 d2 d3. c (t d1 d2 d3))
     -> c a
ext3 def ext = maybe def (id) (gcast3' ext)

gcast3' :: (Typeable3 t, Data a) => c (t f g h) -> Maybe (c a)
gcast3' x = r
 where
  r = if typeOf3 (getArg x) == typeOf3' (getArg (fromJust r))
       then Just $ unsafeCoerce x
       else Nothing
  getArg :: c x -> x
  getArg = undefined
  typeOf3' z = mkTyConApp (typeRepTyCon (typeOf z)) []

在 GHC 8.4 上,这个不再编译。 - Turion
这个简单的函数甚至都不能工作:thing :: (Typeable t) => (forall b c d . (Data b, Data c, Data d) => f (t b c d)) -> TypeRep thing = typeRepGHC 报错:错误: * 无法推断出 (Data b0) 条件为: Typeable t 绑定于下面的类型签名: thing :: forall (t :: * -> * -> * -> *) (f :: * -> *). Typeable t => (forall b c d. (Data b, Data c, Data d) => f (t b c d)) -> TypeRep [...] 类型变量 `b0' 不明确 - Turion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接