作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Haskell 数据类型,比如
data Mytype
= C1
| C2 Char
| C3 Int String
case
在
Mytype
忘记处理其中一种情况,GHC 给了我一个警告(穷举检查)。
Arbitrary
实例生成
MyTypes
喜欢:
instance Arbitrary Mytype where
arbitrary = do
n <- choose (1, 3 :: Int)
case n of
1 -> C1
2 -> C2 <$> arbitrary
3 -> C3 <$> arbitrary <*> someCustomGen
Mytype
添加一个新的替代品。并忘记更新 Arbitrary 实例,因此我的测试不会测试该替代方案。
arbitrary = do
x <- elements [C1, C2 undefined, C3 undefined undefined]
case x of
C1 -> C1
C2 _ -> C2 <$> arbitrary
C3 _ _ -> C3 <$> arbitrary <*> someCustomGen
最佳答案
我使用 TemplateHaskell 实现了一个解决方案,您可以在 https://gist.github.com/nh2/d982e2ca4280a03364a8 找到原型(prototype).有了这个,你可以写:
instance Arbitrary Mytype where
arbitrary = oneof $(exhaustivenessCheck ''Mytype [|
[ pure C1
, C2 <$> arbitrary
, C3 <$> arbitrary <*> arbitrary
]
|])
''Mytype
)和一个表达式(在我的例子中是
arbitrary
样式的列表
Gen
s)。它获取该类型名称的所有构造函数的列表,并检查表达式是否包含所有这些构造函数至少一次。如果您刚刚添加了一个构造函数但忘记将其添加到 Arbitrary 实例,则此函数将在编译时警告您。
exhaustivenessCheck :: Name -> Q Exp -> Q Exp
exhaustivenessCheck tyName qList = do
tyInfo <- reify tyName
let conNames = case tyInfo of
TyConI (DataD _cxt _name _tyVarBndrs cons _derives) -> map conNameOf cons
_ -> fail "exhaustivenessCheck: Can only handle simple data declarations"
list <- qList
case list of
input@(ListE l) -> do
-- We could be more specific by searching for `ConE`s in `l`
let cons = toListOf tinplate l :: [Name]
case filter (`notElem` cons) conNames of
[] -> return input
missings -> fail $ "exhaustivenessCheck: missing case: " ++ show missings
_ -> fail "exhaustivenessCheck: argument must be a list"
GHC.Generics
轻松遍历
Exp
的语法树: 与
toListOf tinplate exp :: [Name]
(来自
lens
)我可以轻松找到所有
Name
s 整体
exp
.
Language.Haskell.TH
中的类型没有
Generic
实例,并且(使用当前的 GHC 7.8)都没有
Integer
或
Word8
-
Generic
这些实例是必需的,因为它们出现在
Exp
中。 .所以我将它们添加为孤立实例(对于大多数情况,
StandaloneDeriving
会这样做,但对于像
Integer
这样的原始类型,我必须复制粘贴实例,因为
Int
有它们)。
case
这样的详尽检查器。确实如此,但正如我们同意的那样,在保持 DRY 的情况下这是不可能的,而且这个 TH 解决方案是 DRY。
exhaustivenessCheck
。在每个任意实例内。
关于haskell - QuickCheck:如何使用穷举检查器来防止被遗忘的 sum 类型的构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25535616/
我们有一个可连接的(当我们连接时,我们被要求配对,见问题 2)我们已经制造并为其编写了 iOS 应用程序的蓝牙 4.0 外围设备。 问题一 在带有 CoreBluetooth 的 iOS 6 中,是否
我是一名优秀的程序员,十分优秀!