我错误地将
length
应用于 (pa,ir)
,并花了一点时间才发现,因为代码可以编译!
所以我查了一下
:t length
,它告诉我它的参数只需要是一个Foldable
。
Foldable
有一个(,)
实例:
instance Foldable ((,) a) where
foldMap f (_, y) = f y
foldr f z (_, y) = f y z
length _ = 1
null _ = False
length
的自动定义。
Foldable
的 (,)
实例有何用处?特别是考虑到它的一些最小定义(null
和length
)无论如何都已被覆盖。
相关问题.
TL;DR有用吗?有争议的。与其他类型构造函数一致吗?是的。
--
考虑
Identity
的实例:
-- abbreviated to match the instance in your question
instance Foldable Identity where
foldMap = coerce
foldr f z (Identity x) = f x z
length _ = 1
null _ = False
这与将
Identity
本身视为与 (,) ()
同构是一致的:
i2t :: Identity a -> ((), a)
i2t (Identity x) = ((), x)
t2i :: ((), a) -> Identity a
t2i ((), x) = Identity x
每种情况下的“用处”是将元组视为用某种其他类型的值“标记”的单个值。对于
(,) a
,标签的类型为 a
。对于 (,) ()
和 Identity
,标签要么没有信息,要么完全不存在。折叠这样的类型相当于忽略或剥离标签并直接使用包装的值。
可以为
(,,)
等定义类似的实例,只需调整匹配并忽略标签的模式即可。例如,
instance Foldable ((,,) a b) where
foldMap f (_, _, y) = f y
foldr f z (_, _, y) = f y z
length _ = 1
null _ = False
您似乎可以类似地为单位类型定义一个实例(不包含在
Data.Foldable
中):
instance Foldable () where
foldMap = coerce
foldr f z () = f () z
length () = 0
null () = True
与
()
作为空元组的解释一致。不仅没有标签,而且也没有值 to 标签。
由于我忽略的原因,这不是一个有效的实例,或者即使对于包括
Foldable ((,) a)
的人来说,它也被认为太无用了。