我正在寻找一种安全的方式来为数据类型生成实例 其中有没有派生类的字段,但这样的字段有 通用实例。
我认为这是使用QuickCheck进行测试的非常流行的案例, 因为每种类型都应该有任意的。 没有人愿意在生产中包含任意实例,但是 否则派生测试模块中的任意问题孤立警告。
我可以在测试模块中为用户定义 newtype,但我不能对 Name 类型做同样的事情。它是在用户内部硬编码的。
我了解孤儿实例的问题。它们可以重叠,但 在这里,我希望 GHC 在递归为 UserAr 派生任意期间为 Name 派生一个隐藏的任意实例。 这种名称的任意实例应该在 UserAr 的任意实例中,就像我手动编写它一样。 我认为从技术上讲,至少通过模板哈斯克尔必须是可行的。 所以我询问细节。
-- prod
import GHC.Generics
newtype Name = Name String deriving (Show, Generic)
data User = User Name deriving (Show, Generic)
-- test
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype UserAr = UserAr User deriving (Show, Arbitrary)
Haskell中没有隐藏实例这样的东西。拥有不能在模块外部使用的实例的唯一方法是隐藏它所在的整个类型。为此,您需要为该类型创建一个newtype
包装器,并且仅导出没有实例的包装器。然后,您可以使用GeneralizedNewtypeDeriving
和/或DerivingVia
来获取所需的其他实例。