【发布时间】:2021-01-01 19:56:37
【问题描述】:
我正在处理精彩的Haskell Book。在 Traversable 章节(21)的最后,我需要为下面的 Tree 写一个实例:
data Tree a =
Empty
| Leaf a
| Node (Tree a) a (Tree a)
这是我的解决方案的a link to the full code。练习建议尝试同时实现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}
我怀疑 QuickCheck 正在使用的 folding 函数有什么我不明白的地方。
问题:
- 为什么会出现故障?
- 有没有办法通过 QuickCheck 获取测试中使用的函数?
【问题讨论】:
标签: haskell typeclass quickcheck foldable typeclass-laws