haskell - 在 Data.Foldable 的意义上,有哪些可折叠的实例_不是_“一般可折叠结构”?
问题描述
文档Foldable
列出了“通用可折叠结构”所需的几个属性:
对于
foldr
:对于一般的可折叠结构,这在语义上应该是相同的,
foldr f z = foldr f z . toList
对于
foldl
:对于一般的可折叠结构,这在语义上应该是相同的,
foldl f z = foldl f z . toList
对于
foldl'
(对我来说看起来像是一个错字):对于一般的可折叠结构,这在语义上应该是相同的,
foldl f z = foldl' f z . toList
Foldable
这些属性不需要或不能保持的情况有哪些?
解决方案
据我了解,如果实例定义了这些可选功能,这些是实例必须遵守的规则。默认情况下,Foldable
实例只需要定义foldMap
或foldr
。根据这两个定义之一,类型类的所有其他功能都会自动遵循。
然而,通常,类型类让您可以选择定义更多类型类的行为。toList
如果默认的自动定义效率低下,并且您希望提供更有效的实现,这将很有用。Monoid
对于类型类,这可能更容易理解,它定义mconcat
为可选函数“以便可以为特定类型提供优化版本”。
如果您选择自己定义部分或全部这些功能,则 OP 中引用的法律是实例必须遵守的法律。作为违反规则的(无意义的)类型的示例,请考虑以下Invalid
类型:
import Data.Foldable
data Invalid a = Invalid a deriving (Show, Eq)
instance Foldable Invalid where
foldMap f (Invalid x) = f x
foldr _ x _ = x -- Unlawful!!
toList (Invalid x) = [x]
虽然它只需要定义foldMap
为一个Foldable
实例,但这个也定义了foldr
and toList
。虽然toList
定义很好,但foldr
定义违反了规则:
*Q53460772 Data.Monoid Data.Foldable> toList $ Invalid 42
[42]
*Q53460772 Data.Monoid Data.Foldable> foldMap Sum $ Invalid 42
Sum {getSum = 42}
*Q53460772 Data.Monoid Data.Foldable> f = \x acc -> x + acc
*Q53460772 Data.Monoid Data.Foldable> z = 0
*Q53460772 Data.Monoid Data.Foldable> (foldr f z . toList) $ Invalid 42
42
*Q53460772 Data.Monoid Data.Foldable> foldr f z $ Invalid 42
0
toList
andfoldMap
函数的行为与您期望的一样,但请注意它不会foldr f z
产生与foldr f z . toList
.
虽然Invalid
是一个无意义的示例,但它表明您可以编写可编译的代码,并且看起来它提供了Foldable
. 然而,与每个功能相关的法律和规则清楚地表明这不是一个有效的实例。
推荐阅读
- date - 查找两个日期之间的工作日数 TERADATA
- spring-boot - 如何在 Spring Boot JPA 中从 1 开始而不是从 0 进行分页
- r - 计算 r 中的文本数量
- python - 如何在 django 模型中在另一个表上创建实例时更改一个表上的值?
- gdal - TerraSAR X 单位转换
- python - 使用 pyinstaller 将文件添加到 exe 中?
- python - Eigen 中是否有与 triu_indices (numpy) 等价的东西?
- python - Python - Excel 到 HTML(保持格式)
- javascript - 通过 JavaScript 预加载/预取大量远程图像
- powershell - 当单词不存在时创建循环