Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an equivalent to head/tail for Foldable functors in general?

I would like to express the following Haskell code, using only functor algebra (i.e. - not relying on any specific container type, such as List):

ys = zipWith (+) (head xs : repeat 0)
                 (tail xs ++ [y])

It seems to me that there ought to be a way to do this, relying only on Foldable (or, maybe, Traversable), but I can't see it.

I'm wondering:

  1. Is there a general notion of first and rest for Foldable/Traversable functors?
  2. Is there an accepted idiomatic way, using only functor algebra, to shift the contents of a Foldable/Traversable functor? (Note that the computation above might be described in English as, "Shift in one value from the right, and add back the value that falls of on the left to the new first value.")
like image 759
dbanas Avatar asked Jun 10 '18 15:06

dbanas


1 Answers

You can find the first or last element of a Foldable using the First or Last monoids from Data.Monoid.

foldMap (Last . Just)  :: Foldable t => t a -> Last a
foldMap (First . Just) :: Foldable t => t a -> First a

All Foldable are convertible to a list, and so because you can find the head and tail of a list, you can do so for any Foldable.

toList = foldr (:) [] :: Foldable t => t a -> [a]

That said, the tail will have a list type and not that of the Foldable (unless it was too a list). This is ultimately because not all that is Foldable can implement an uncons. For example:

data Pair a = Pair a a

This is Foldable, but you could not represent the tail of a Pair using a Pair.

like image 64
erisco Avatar answered Nov 15 '22 11:11

erisco