Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of 'fmapDefault' in 'Data.Traversable'?

I'm looking at the documentation for Data.Traversable and came across fmapDefault - https://downloads.haskell.org/~ghc/latest/docs/html/libraries/base/Data-Traversable.html#g:3

fmapDefault :: Traversable t => (a -> b) -> t a -> t b

The documentation states that -

This function may be used as a value for fmap in a Functor instance, provided that traverse is defined.

So presumably it can be used to derive an fmap for a Traversable instance. However, Traversable has Functor as a superclass.

class (Functor t, Foldable t) => Traversable t where
    ...

So you cannot define a Traversable instance without defining the Functor instance first! And wherever you have a Traversable, you have access to an fmap, which is equivalent to (and perhaps more efficient than) fmapDefault.

So where would one use fmapDefault, instead of the much more familiar fmap?

like image 332
Anupam Jain Avatar asked Jul 05 '15 11:07

Anupam Jain


People also ask

What is traversable Haskell?

Class of data structures that can be traversed from left to right, performing an action on each element. Instances are expected to satisfy the listed laws. class (Functor t, Foldable t) => Traversable t where.

What is Fmap in Haskell?

You can think of fmap as either a function that takes a function and a functor and then maps that function over the functor, or you can think of it as a function that takes a function and lifts that function so that it operates on functors. Both views are correct and in Haskell, equivalent.


1 Answers

It allows you to write

data Foo a = ...

instance Functor Foo where -- we do define the functor instance, but we “cheat”
  fmap = fmapDefault       -- by using `Traversable` in its implementation!

instance Traversable Foo where
  traverse = ...           -- only do this manually.

That said, I don't think this is really sensible. Functor instances are usually trivial to do by hand, and the obvious implementation will indeed likely be more efficient than a Traversable derived one. Usually, the instance can in fact be created automatically:

{-# LANGUAGE DeriveFunctor #-}

data Foo a = ...
       deriving (Functor)
like image 174
leftaroundabout Avatar answered Sep 21 '22 03:09

leftaroundabout