[英]What's the point of map in Haskell, when there is fmap?
在我嘗試使用map
, fmap
也能正常工作。 為什么 Haskell 的創建者會覺得需要一個map
函數? 難道它不能只是目前已知的fmap
並且fmap
可以從語言中刪除嗎?
我想回答一下以引起人們對augustss 評論的關注:
實際情況並非如此。 發生的事情是映射的類型在 Haskell 1.3 中被泛化為涵蓋 Functor。 即,在 Haskell 1.3 fmap 中被稱為 map。 此更改隨后在 Haskell 1.4 中恢復,並引入了 fmap。 這種變化的原因是教學上的; 在向初學者教授 Haskell 時,非常通用的映射類型使錯誤消息更難以理解。 在我看來,這不是解決問題的正確方法。
Haskell 98 被一些 Haskells(包括我)視為倒退,以前的版本定義了一個更抽象和一致的庫。 那好吧。
它們在應用程序站點上看起來相同,但當然它們是不同的。 當您將這兩個函數map
或fmap
中的任何一個fmap
值列表時,它們將產生相同的結果,但這並不意味着它們的目的相同。
運行 GHCI 會話(Glasgow Haskell Compiler Interactive)以查詢有關這兩個函數的信息,然后查看它們的實現,您會發現許多差異。
查詢 GHCI 以獲取有關map
信息
Prelude> :info map
map :: (a -> b) -> [a] -> [b] -- Defined in ‘GHC.Base’
你會看到它被定義為一個高階函數,適用於任何類型a
的值列表,產生任何類型b
的值列表。 盡管是多態的(上面定義中的a
和b
代表任何類型),但map
函數旨在應用於值列表,這只是 Haskell 中許多其他數據類型中的一種。 map
函數無法應用於不是值列表的內容。
從GHC.Base源碼可以看出, map
函數的實現如下
map _ [] = []
map f (x:xs) = f x : map f xs
它利用模式匹配將列表的頭部( x
)從列表的尾部( xs
)中拉出,然后使用:
(cons)值構造函數構造一個新列表,以便在fx
(將其讀作“f應用到 x" ) 到尾部的map
遞歸,直到列表為空。 值得注意的是, map
函數的實現不依賴於任何其他函數,而只依賴於它自己。
現在嘗試查詢有關fmap
信息,您將看到完全不同的內容。
Prelude> :info fmap
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
...
-- Defined in ‘GHC.Base’
這次fmap
被定義為一種函數,其實現必須由希望屬於Functor
類型類的那些數據類型提供。 這意味着可以有多個數據類型,而不僅僅是“值列表”數據類型,能夠為fmap
函數提供實現。 這使得fmap
適用於更大的數據類型集:確實是函子!
正如您可以從GHC.Base源代碼中讀到的, fmap
函數的一種可能實現是由Maybe
數據類型提供的:
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
另一種可能的實現是由 2-tuple 數據類型提供的實現
instance Functor ((,) a) where
fmap f (x,y) = (x, f y)
另一種可能的實現是列表數據類型提供的實現(當然!):
instance Functor [] where
fmap f xs = map f xs
它依賴於map
函數。
map
函數只能應用於值列表(其中值是任何類型),而fmap
函數可以應用於更多數據類型:所有屬於函子類的數據類型(例如,mays、tuples、lists、等等。)。 由於“值列表”數據類型也是一個函子(因為它為它提供了一個實現),因此fmap
可以應用於產生與map
完全相同的結果。
map (+3) [1..5]
fmap (+3) (Just 15)
fmap (+3) (5, 7)
引用https://wiki.haskell.org/Typeclassopedia#Functor 上的Functor
文檔
你可能會問為什么我們需要一個單獨的
map
函數。 為什么不取消當前的僅列表map
函數,而是將fmap
重命名為map
呢? 嗯,這是個好問題。 通常的論點是,剛學習 Haskell 的人,在錯誤地使用map
,更願意看到關於列表的錯誤,而不是關於Functor
的錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.