Neden map, fmap ve liftM var?


102
map :: (a -> b) -> [a] -> [b]

fmap :: Functor f => (a -> b) -> f a -> f b

liftM :: Monad m => (a -> b) -> m a -> m b

Neden esasen aynı şeyi yapan üç farklı işleve sahibiz?


32
Çoğunlukla tarih. fmap pedagojik nedenlerle haritadan farklıdır, liftM tarihsel nedenlerden dolayı fmap'ten farklıdır (yani Functor, Monad'ın bir üst sınıfı değildir)
luqui

12
Oh, ve sadece açık olmak adına: "Aslında" aynı şeyi yapmıyorlar. Hem mapve liftMkesinlikle yapmalıyım tam olarak aynı şeyi fmap.
CA McCann

2
Tam olarak aynı şeyi yaparken fmapve yaparken , elbette sadece özel bir durum, yani farklı bir şey. iyi yazılmış, oysa değil. liftMmapfmap id getLinemap id getLine
Thorsten

Yanıtlar:


91

mapListeler üzerindeki işlemleri basitleştirmek için ve tarihsel nedenlerle mevcuttur (bkz . fmap varken Haskell'de haritanın amacı nedir? ).

Neden ayrı bir harita işlevine ihtiyacımız olduğunu sorabilirsiniz. Neden sadece listeye dayalı geçerli harita işlevini ortadan kaldırıp bunun yerine fmap'i eşlemek için yeniden adlandırmıyorsunuz? Bu güzel bir soru. Genel argüman, haritayı yanlış kullanarak Haskell'i yeni öğrenen birinin, Functors'dan çok listeler hakkında bir hata görmeyi tercih etmesidir.

- Typeclassopedia , Sayfa 20

fmapve liftMHaskell'de monadlar otomatik olarak işlev görmediği için var:

Hem fmap hem de liftM'ye sahip olmamız, matematiksel olarak konuşulsa bile, Monad türü sınıfın bir Functor örneği gerektirmemesinin talihsiz bir sonucudur, her monad bir functordur. Bununla birlikte, fmap ve liftM esasen birbirinin yerine kullanılabilir, çünkü (teknik anlamda değil sosyal anlamda) herhangi bir tipin aynı zamanda bir Functor örneği olmaksızın Monad'ın bir örneği olması için bir hatadır.

- Typeclassopedia , Sayfa 33

Düzenleme: agustuss'un tarihi mapve fmap:

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'de fmap varken haritanın anlamı nedir?


14
Ve benim bakış açıma göre, @augustss'un tanımladığı değişiklik yapıldıktan on yıldan fazla bir süre sonra Haskell ile ilk karşılaşan ve şu anda dili öğrenen insanlara yardım etmek için çok zaman harcayan biri olarak, bunun yardımcı olduğu bile açık değil. herhangi bir şekilde. Yararsız fazlalığı telafi etmek için kesinlikle yeterli değil (ki bu da insanların buna benzer sorular sormasına neden oluyor); Functorsınıf göz ardı edilemeyecek kadar yaygın olduğunu ve yeni başlayanlar genellikle zaten hata mesajları ile karıştı!
CA McCann

11
Kaldıramaz mıyız liftM? Bırakın kod kırılsın, kimin umurunda, kodun github'da düzeltilmesi ve ardından hackage'a yüklenmesi genellikle 2 günden az sürer. Yoksa çılgın ve çılgın mıyım?
Tarrasch

1
@Tarrasch: Herkes github kullanmaz, tüm paketlerin zamanında güncellenme konusunda harika bir sicili yoktur ve ben kullandığım zamana daha iyi uyduğundan liftMziyade bir do-block içinde kullanma eğilimindeyim , vb. yanı sıra. fmapliftM2
ivanm

1
@ L01man insanlar bunun üzerinde çalıştı; stackoverflow.com/questions/5730270/… bakın ve en azından sayısal sınıflar için alternatifler vardır: hackage.haskell.org/packages/archive/numeric-prelude/0.3.0.2/…
li.davidm

1
@ L01man Evet, bu yakında düzeltilecek. Uygulamalı Monad Öneri bunun Haskell yeni şekli ile geçecek gibi (AMP) görünüyor. GHC 7.8.3 , --fwarn-ampgeçiş için mevcut kodun güncellenmesine yardımcı olacak yeni bir işarete sahiptir .
recursion.ninja
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.