Haskell'de fmap varken haritanın anlamı nedir?


99

Ben kullanarak denedim her yer map, fmapsıra çalıştı. Haskell'in yaratıcıları neden bir mapişleve ihtiyaç duydular ? Sadece şu anda bilinen fmapve fmapdilden kaldırılabilen şey olamaz mı?


13
Sanırım 'Haskell'de fmap'in anlamı nedir' diye soruyorsunuz?
zw324

12
Amacının ne olduğunu biliyorum fmap. Bir Functor örneği üzerinden bir işlevi eşlemek içindir. Uzmanlaşmanın amacını merak ediyorum map.
Clark Gaebel

Yanıtlar:


95

Augusts'un yorumuna dikkat çekmek için bir cevap vermek istiyorum :

Aslında böyle olmuyor. Haskell 1.3'te harita türünün Functor'u kapsayacak şekilde genelleştirilmesi oldu. Yani, Haskell'de 1.3 fmap harita olarak adlandırıldı. Bu değişiklik daha sonra Haskell 1.4'te geri alındı ​​ve fmap kullanıma sunuldu. Bu değişikliğin nedeni pedagojikti; Haskell'i yeni başlayanlara öğretirken, çok genel bir harita türü hata mesajlarının anlaşılmasını zorlaştırdı. Kanımca sorunu çözmenin doğru yolu bu değildi.

Haskell 98, bazı Haskellers (ben dahil) tarafından geriye doğru bir adım olarak görülüyor, önceki sürümler daha soyut ve tutarlı bir kitaplık tanımlamıştı. Oh iyi.


16
Bu geriye dönük adımlar herhangi bir yerde toplanıp belgelenmiş mi? Başka neyin geri adım olarak kabul edildiğini ve bunlara daha iyi çözümler olup olmadığını görmek ilginç olurdu.
Davorak

3
map and fmapUzun zamandır etrafında olmuştur - bu Ağustos 2006'da Haskell-asal posta listesinde ısıtılmış - haskell.org/pipermail/haskell-prime/2006-August/thread.html . Bir kontrpuan olarak statükoyu tercih ederim. Bana göre, kabaca Miranda'ya karşılık gelen bir Haskell alt kümesi olması değerli görünüyor. İngiltere'de Miranda, yalnızca bilgisayar bilimi öğrencileri için değil, matematik öğrencileri için bir öğretim dili olarak kullanıldı. Bu niş işlevsel olmayan bir dil (örneğin Mathematica) için kaybolmamışsa Haskell'i birleşik bir mapdoldurma ile görmüyorum .
stephen tetley

35
Ve ayrıca şunu da belirtmek isterim ki, halihazırda farkında olmayanlar için, Augustss, tüm pratik amaçlar için Haskell'in varlığından bu yana Haskell topluluğunun bir parçası olan Lennart Augustsson, krş. Bir Haskell Tarihi , dolayısıyla söz konusu yorum hiçbir şekilde ikinci el bir söylenti değil!
CA McCann

3
Artık Haskell wiki'de bu sorunun bahsedildiği Nitpicks sayfası var.
Alexey

1
Bu kararın pedagojik nedenlerle verilmesi komik, çünkü Haskell'i öğrenirken her zaman fmap'i flatmap ile karıştırdım. Birlikte bir n00b odak grubu almaları gerekirdi. :)
Danny Andrews

28

Https://wiki.haskell.org/Typeclassopedia#Functor adresindekiFunctor belgelerden alıntı yapma

Neden ayrı bir mapişleve ihtiyacımız olduğunu sorabilirsiniz . Neden sadece şimdiki liste salt ortadan mapfonksiyonu ve yeniden adlandırmak fmapiçin map yerine? Bu güzel bir soru. Olağan argüman, Haskell'i yeni öğrenen birinin, mapyanlış kullanırken , listeler hakkında bir hata görmekten çok, daha çok görmeyi tercih etmesidir Functor.


1
Bu bana çok mantıklı geliyor.
hbobenicio

25

Uygulama sitesinde aynı görünüyorlar ama elbette farklılar. Bu iki işlevden birini mapveya fmapbir değerler listesine uyguladığınızda , aynı sonucu üretirler ancak bu, aynı amaç için tasarlandıkları anlamına gelmez.

Bu iki işlev hakkında bilgi sorgulamak için bir GHCI oturumu (Glasgow Haskell Compiler Interactive) çalıştırın, ardından uygulamalarına bir göz atın ve birçok farkı keşfedeceksiniz.

harita

GHCI sorgusu hakkında bilgi için map

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

ve herhangi bir türden adeğerlerin bir listesini veren herhangi bir türden değer listesine uygulanabilen yüksek dereceli bir işlev olarak tanımlandığını göreceksiniz b. Polimorfik ( ave byukarıdaki tanımdaki herhangi bir türü ifade etmesine rağmen ), mapişlevin Haskell'deki diğer birçok veri türü arasında yalnızca bir olası veri türü olan bir değerler listesine uygulanması amaçlanmıştır . mapFonksiyon değerlerinin bir listesi değildir şeye uygulanamadı.

GHC.Base kaynak kodundan okuyabileceğiniz gibi , mapişlev aşağıdaki gibi uygulanır

map _ []     = []
map f (x:xs) = f x : map f xs

bu , listenin başını ( x) kuyruğundan (the xs) dışarı çekmek için desen eşleştirmeden yararlanır , ardından :(eksileri) değer oluşturucusunu kullanarak yeni bir liste oluşturur f x( "f, x'e uygulandı" olarak okuyun ) mapliste boşalana kadar üst üste yineleme . mapİşlevin uygulanmasının başka herhangi bir işleve değil, yalnızca kendisine bağlı olduğunu belirtmek gerekir.

fmap

Şimdi hakkında bilgi için sorgulamaya çalışın fmapve oldukça farklı bir şey göreceksiniz.

Prelude> :info fmap
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  ...
  -- Defined in ‘GHC.Base’

Bu zaman fmap, uygulamaları Functortür sınıfına ait olmak isteyen veri türleri tarafından sağlanması gereken işlevlerden biri olarak tanımlanır . Bu , işlev için bir uygulama sağlayabilen yalnızca "değerler listesi" veri türü değil, birden fazla veri türü olabileceği anlamına gelir fmap. Bu, fmapçok daha geniş bir veri türü kümesine uygulanabilir: gerçekten de işlevciler!

GHC.Base kaynak kodundan okuyabileceğiniz gibi, işlevin olası bir uygulaması fmap, Maybeveri türü tarafından sağlanandır :

instance  Functor Maybe  where
  fmap _ Nothing       = Nothing
  fmap f (Just a)      = Just (f a)

ve bir başka olası uygulama, 2 tuple veri türü tarafından sağlanan olandır

instance Functor ((,) a) where
  fmap f (x,y) = (x, f y)

ve başka bir olası uygulama, liste veri türü tarafından sağlanan uygulamadır (tabii ki!):

instance  Functor []  where
  fmap f xs = map f xs

hangi mapfonksiyona bağlıdır.

Sonuç

mapOysa fonksiyonu (değerlerinin herhangi bir tiptedir) değerlerinin listesi daha fazla bir şey uygulanabilir fmapfonksiyonu çok daha fazla veri türleri uygulanabilir: funktoru sınıfına ait olanlar (örneğin Belkiler, küpe, listeler, vb her ). Yana "değerler listesi" o (bunun için bir uygulama sağlar, çünkü) veri türü bir funktor da fmaphem de aynı sonuçları üretmektedir uygulanabilir map.

map  (+3) [1..5]
fmap (+3) (Just 15)
fmap (+3) (5, 7)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.