2015-07-05 26 views
8

我在看的文檔Data.Traversable和碰到fmapDefault - https://downloads.haskell.org/~ghc/latest/docs/html/libraries/base/Data-Traversable.html#g:3'Data.Traversable'中的'fmapDefault'有什麼意義?

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

的文檔狀態 -

該功能可以作爲一個函子實例FMAP值,只要定義了遍歷。

因此推測它可以用於派生的Traversable實例。但是,Traversable作爲超類具有Functor

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

所以,你如果不首先定義Functor實例定義Traversable實例!無論您在哪裏擁有Traversable,都可以訪問fmap,這相當於(也可能比fmapDefault更高效)。

那麼在哪裏使用fmapDefault,而不是更熟悉的fmap

+2

「如果不先定義'Functor'實例,就不能定義'Traversable'實例!那麼,「第一」是這樣一個瘋狂的術語... –

+0

是的,這是一個大腦放屁。就像假設1在2之前,由於多年來從0到10的程序性計數。然後你考慮這個問題 - 首先是什麼,'-1'或'-2',並且是開明的。 –

回答

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. 

這麼說,我不認爲這是真懂事。函數實例通常無關緊要,而且明顯的實現可能會比衍生出來的更有效。通常情況下,實例實際上可以自動創建:

{-# LANGUAGE DeriveFunctor #-} 

data Foo a = ... 
     deriving (Functor) 
+0

*通常情況下,實例實際上可以自動創建[...] *情況並非總是如此嗎? – Jubobs

+3

@Jubobs:不完全,對於一些GADT,我已經通過DeriveFunctor獲得了良好的肯定性錯誤。但是這可能只是GHC-7.8中的一個bug。 – leftaroundabout

+2

該死的,我不自覺地認爲'子類'的定義不能引用'超類'的定義。顯然這在事後看來是一種任意的要求。這就是當你必須在一半時間內使用<一天中的OOP語言時纔得到的結果。 –