我读到,LineChartRenderer.swift
可以使用map
定义,即它是一个原始的递归函数。至少对于名单。
现在我的问题:为什么Functor不是Foldable的子类型?如果foldr
只能根据列表的fmap
来定义,那么它们的特殊性是什么?
使用foldr查看foldr
的定义:
map
我可以使用Monoids来:
myMap f xs = foldr step [] xs
where step x ys = f x : ys
但遗憾的是,我没有足够的Haskell魔术师逃脱myMap f xs = foldr step mempty xs
where step x ys = f x : ys
。
答案 0 :(得分:8)
但遗憾的是,我对一个Haskell魔术师来说还远远不够侥幸。
你发现了一个根本问题,就是不允许将每个可折叠的玩家都变成玩偶; foldr
会丢弃折叠的结构,仅保留(等于)其元素列表。你不能“逃脱利弊”,因为你无法知道只给出Foldable
个实例的数据结构。
鉴于树的这种(典型的)定义:
data Tree a = Bin a (Tree a) (Tree a) | Tip
instance Functor Tree where
fmap f (Bin a l r) = Bin (f a) (fmap f l) (fmap f r)
fmap _ Tip = Tip
instance Foldable Tree where
foldMap f (Bin a l r) = foldMap f l <> f a <> foldMap f r
foldMap _ Tip = mempty
比较这两棵树:
let x = Bin 'b' (Bin 'a' Tip Tip) Tip
let y = Bin 'a' Tip (Bin 'b' Tip Tip)
两棵树都有toList
的“ab”,但明显不同。这意味着折叠树的行为会丢失一些您无法恢复的信息(即左子树,右子树和元素之间的边界)。由于您无法使用Foldable
实例的结果区分x和y,因此您不能仅使用这些方法编写fmap
fmap id == id
。我们不得不求助于模式匹配并使用构造函数来写出Functor
实例。