我有一个编码和工作的模块,但是我无法为它输入两个功能签名,因为输入它们我必须为模块启用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
而没有任何问题,这使我能够使用SqlBackend
和& ICanReturnTo
约束没有问题。
该模块是否存在问题导致无法使用TypeFamilies
进行构建?或者我应该启用另一个扩展来修复它吗?我没想到只是启用该扩展来打破编译。
答案 0 :(得分:9)
如果您启用了~
或TypeFamilies
,则只能写出类型等式约束GADTs
。
但是,启用TypeFamilies
或GADTs
也会启用MonoLocalBinds
.正如名称所示,它会禁用本地定义变量的泛化。
如果MonoLocalBinds
阻止编译代码,您应该写出通用类型签名,或将这些本地因素分解为顶级定义。有时写出广义类型有点困难;在这种情况下,您可以尝试查询GHCi,或者您可以启用NoMonomorphismRestriction
,编写未注释的顶级定义,然后查看推断的类型。