我正在阅读精彩的Haskell Book。在 Traversable 章节(21)的最后,我需要为以下 Tree 编写一个实例:
data Tree a =
Empty
| Leaf a
| Node (Tree a) a (Tree a)
这是我的解决方案的完整代码的链接。练习建议尝试同时实现foldMap
和foldr
。这就是我的实现方式foldr
(对调用顺序没有太多考虑):
foldr _ z Empty = z
foldr f z (Leaf x) = f x z
foldr f z (Node left x right) =
f x $ foldr f (foldr f z left) right
然后我实现foldMap
如下:
foldMap f Empty = mempty
foldMap f (Leaf x) = f x
foldMap f (Node left x right) =
foldMap f left <> f x <> foldMap f right
当我运行 QuickCheck 的foldable
测试批次时,我遇到了一些失败。将我的foldr
实现更改为以下内容会使所有测试通过:
foldr _ z Empty = z
foldr f z (Leaf x) = f x z
foldr f z (Node left x right) =
foldr f (f x (foldr f z right)) left
我尝试自己运行失败的测试用例,但无法重新创建失败:
*Ch21_12_ExercisesTree Data.Monoid> tree = Node (Node (Leaf (-5)) 3 (Node (Leaf 3) 5 Empty)) (-2) Empty
*Ch21_12_ExercisesTree Data.Monoid> foldr (<>) (mempty :: Sum Int) t
Sum {getSum = 4}
*Ch21_12_ExercisesTree Data.Monoid> foldMap Sum t
Sum {getSum = 4}
fold
我怀疑QuickCheck 正在使用的 ing 函数有什么我没有弄清楚的地方。
问题:
- 为什么会出现故障?
- 有没有办法通过 QuickCheck 获取测试中使用的功能?