在Haskell中,我们看到Foldable and Traversable landing in Haskell prelude。
这些都在sequences上进行操作。
Prelude Data.Sequence> map (\n -> replicate n 'a') [1,3,5]
["a","aaa","aaaaa"]
Prelude Data.Sequence> fmap (\n -> replicate n 'a') (1 <| 3 <| 5 <| empty)
fromList ["a","aaa","aaaaa"]
我的问题是相当于Haskell的Foldable和Traversable只是一个sequence in Clojure?
假设:
答案 0 :(得分:16)
否。虽然任何代表有限元素序列的Functor
都是Traversable
(因此Foldable
),但还有很多其他结构Traversable
,但不是序列式的,因为他们没有明显的连接概念。将有一种方法来获得包含元素的序列,但结构可能不仅仅包含该序列。
Traversable f
实际上是什么意思是f x
类型的结构包含有限数量的x
类型的元素,并且有一些方法traverse
结构正好访问x
的每个元素一次。所以像#34;语法中的术语,被视为包含变量&#34;可以是Traversable
。
data Term x
= Var x
| Val Integer
| Add (Term x) (Term x)
instance Traversable Term where
traverse f (Var x) = pure Var <*> f x
traverse f (Val i) = pure (Val i)
traverse f (Add s t) = pure Add <*> traverse f s <*> traverse f t
您始终可以使用traverse
对所有元素执行操作。我们通过将fmap
和pure = id
作为普通申请来获得<*>
。
instance Functor Term where
fmap = fmapDefault
,其中
fmap :: (x -> y) -> Term x -> Term y
实现同时重命名。
同时,Foldable
实例
instance Foldable Term where
foldMap = foldMapDefault
使pure
将一些monoid和<*>
的中性元素赋予组合操作,因此我们得到类似reduce的操作。如,
foldMap (:[]) :: Term x -> [x]
给出了术语中出现的变量列表。也就是说,我们总是可以从Traversable
数据中获取元素序列,但数据可能具有除这些元素之外的结构。 Term
具有变量以外的结构(Val
和Add
s),并且不太明确&#34; cons&#34;语法树的意思。
因此,虽然比序列更多的结构是Traversable
,但Traversable
接口为您提供的序列操作更少。 Traversable
的要点是概括 map -like和 reduce -like操作,而不是捕获 list -ness。
答案 1 :(得分:1)
我想在Foldable and Traversable上指出Haskell wiki文档。
首先,可折叠和可遍历是两种不同的类型。对于可折叠,维基页面发表的评论似乎暗示它与Clojure序列几乎相同。每个可折叠都有一个代表作为列表:
toList :: Foldable a => [a]
toList a = foldr (:) [] a
和(纠正我,如果我错了)似乎折叠结构与折叠相关列表相同,即:
foldr f b a = foldr f b (toList a)
在这个等式中,左边的foldr
是通用版本,而右边的那个是列表上的那个。
Haskell和Clojure之间的主要区别在于Clojure要求您自己应用toList
函数,以便在折叠/减少数据结构之前将数据结构转换为序列。对于平面数据结构(即列表,向量,哈希映射......)toList
只是标识函数,因此您看不到它。另一方面,对于像树这样的东西,你需要在折叠它之前调用像tree-seq
这样的函数。