'Data.Traversable'中的'fmapDefault'有什么意义?

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

我正在查看 Data.Traversable 的文档并发现 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

文档指出 -

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

所以大概它可以用于为 Traversable 实例派生 fmap。但是,TraversableFunctor 作为超类。

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

因此,如果不先定义 Functor 实例,就无法定义 Traversable 实例!无论您拥有 Traversable,您都可以访问 fmap,这等同于(并且可能比 fmapDefault.

更有效)

那么在哪里可以使用 fmapDefault,而不是更熟悉的 fmap

它允许你写

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.

话虽如此,我认为这并不明智。 Functor 实例通常用手做起来很简单,而且明显的实现确实可能比 Traversable 派生的更有效。通常,实际上可以自动创建实例:

{-# LANGUAGE DeriveFunctor #-}

data Foo a = ...
       deriving (Functor)