'Data.Traversable'中'fmapDefault'的重点是什么?

Anu*_*ain 8 haskell functor typeclass 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
Run Code Online (Sandbox Code Playgroud)

文件说明 -

如果定义了遍历,则此函数可用作Functor实例中fmap的值.

所以可能它可以用于派生fmap一个Traversable实例.然而,TraversableFunctor一个超类.

class (Functor t, Foldable t) => Traversable t where
    ...
Run Code Online (Sandbox Code Playgroud)

因此,如果不先定义Traversable实例,就无法定义Functor实例!无论你有什么Traversable,你都可以访问fmap,这相当于(也许更有效)fmapDefault.

那么人们会在哪里使用fmapDefault,而不是更熟悉fmap

lef*_*out 11

它允许你写

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.
Run Code Online (Sandbox Code Playgroud)

那就是说,我不认为这是真的明智.Functor实例通常很容易手工完成,明显的实现确实可能比Traversable派生实例更有效.通常,实例实际上可以自动创建:

{-# LANGUAGE DeriveFunctor #-}

data Foo a = ...
       deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

  • @Jubobs:不完全是,对于一些GADT,我在使用'DeriveFunctor`时遇到了很好的错误.但可能这只是GHC-7.8中的一个错误. (3认同)
  • @Jubobs`EndiveFunctor`如果看到以某种方式使用的类型系列也会挽救,即使在你可以证明它仍然是一个有效的函子的情况下. (3认同)
  • 该死的,我下意识地认为'子类'定义不能引用'超类'定义.显然,事后看来这是一个任意的要求.当你必须使用当天的<OOP语言>一半的时候,这就是你得到的. (2认同)