簡體   English   中英

當有 fmap 時,Haskell 中的 map 有什么意義?

[英]What's the point of map in Haskell, when there is fmap?

在我嘗試使用mapfmap也能正常工作。 為什么 Haskell 的創建者會覺得需要一個map函數? 難道它不能只是目前已知的fmap並且fmap可以從語言中刪除嗎?

我想回答一下以引起人們對augustss 評論的關注:

實際情況並非如此。 發生的事情是映射的類型在 Haskell 1.3 中被泛化為涵蓋 Functor。 即,在 Haskell 1.3 fmap 中被稱為 map。 此更改隨后在 Haskell 1.4 中恢復,並引入了 fmap。 這種變化的原因是教學上的; 在向初學者教授 Haskell 時,非常通用的映射類型使錯誤消息更難以理解。 在我看來,這不是解決問題的正確方法。

Haskell 98 被一些 Haskells(包括我)視為倒退,以前的版本定義了一個更抽象和一致的庫。 那好吧。

它們在應用程序站點上看起來相同,但當然它們是不同的。 當您將這兩個函數mapfmap中的任何一個fmap值列表時,它們將產生相同的結果,但這並不意味着它們的目的相同。

運行 GHCI 會話(Glasgow Haskell Compiler Interactive)以查詢有關這兩個函數的信息,然后查看它們的實現,您會發現許多差異。

地圖

查詢 GHCI 以獲取有關map信息

Prelude> :info map
map :: (a -> b) -> [a] -> [b]   -- Defined in ‘GHC.Base’

你會看到它被定義為一個高階函數,適用於任何類型a的值列表,產生任何類型b的值列表。 盡管是多態的(上面定義中的ab代表任何類型),但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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM