启用 TypeFamilies 使代码不再构建

enabling TypeFamilies makes the code not build anymore

我有一个模块编码并且可以工作,但是我无法为它输入两个函数签名,因为要输入它们我必须为模块启用 TypeFamilies 扩展,当我这样做时,它不再构建。

其中一个我需要 TypeFamilies 因为它使用 persisent/esqueleto functions.

我认为正确的类型是:

getByIds :: (PersistEntityBackend a ~ SqlBackend) =>
   EntityField a (Key a) -> [Key a] -> SqlPersistM [Entity a]

(ghc 建议使用更通用的签名)

另一个使用hsqml

ghc 建议使用这个签名,但我想它可以被简化:

  prop :: forall tr b.
          (Marshal tr, Typeable b, MarshalMode tr ICanReturnTo () ~ Yes) =>
          String -> (b -> tr) -> Member (GetObjType (ObjRef b))

最重要的是,没有 TypeFamilies 我无法写下那些签名。但是,在我启用 TypeFamilies 的那一刻,代码不会构建,我不明白为什么。错误看起来像一些多态函数突然变成了单态。

错误输出比较长,大家可以自己找here.

我在应用程序的其他几个模块中启用了 TypeFamilies 没有问题,这使我能够毫无问题地使用 SqlBackendICanReturnTo 约束来编写签名。

该模块是否有问题导致无法使用 TypeFamilies 进行构建?或者我应该启用另一个扩展来修复它吗?没想到只启用那个扩展就破坏了编译。

类型等式约束 ~ 只有在启用 TypeFamiliesGADTs 时才能写出。

但是,启用 TypeFamiliesGADTs 也会启用 MonoLocalBinds. 顾名思义,它会禁用局部定义变量的泛化。

如果 MonoLocalBinds 阻止代码编译,您应该写出通用类型签名或将此类局部变量分解为顶级定义。有时写出泛化类型有点困难;在这种情况下,您可以尝试查询 GHCi,或者您可以启用 NoMonomorphismRestriction,编写未注释的顶级定义,然后查看推断的类型。