No. Whilst any kind of Functor
representing finite sequences of elements will be Traversable
(hence Foldable
), there are plenty of other structures which are Traversable
, but which aren't sequence-like, in that they don't have an obvious notion of concatenation. There will be a way to obtain the sequence of contained elements, but the structure may consist of more than just that sequence.
What Traversable f
means, in effect, is that structures with type f x
contain finitely many elements of type x
, and that there is some way to traverse
the structure visiting each element of x
exactly once. So things like "terms in a syntax, seen as containing variables" can be 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
You can always use traverse
to do operations on all elements. We get fmap
by taking pure = id
and <*>
to be ordinary application.
instance Functor Term where
fmap = fmapDefault
where
fmap :: (x -> y) -> Term x -> Term y
implements simultaneous renaming.
Meanwhile, the Foldable
instance
instance Foldable Term where
foldMap = foldMapDefault
takes pure
to give the neutral element of some monoid and <*>
to the combining operation, so we get reduce-like operations. E.g.,
foldMap (:[]) :: Term x -> [x]
gives the list of variables occurring in a term. That is we can always obtain the sequence of elements from Traversable
data, but the data might have structure other than those elements. Term
s have structure other than variables (their Val
s and Add
s), and it's not so clear what "cons" means for syntax trees.
So, while more structures than sequences are Traversable
, the Traversable
interface offers you fewer sequence-like operations. The point of Traversable
is to generalize map-like and reduce-like operations, not to capture list-ness.