2014-11-09 21 views
13

Ben Haskell öğrenme ve benzeri fonksiyonlarda ortak ekleri fark başladı ediyorum: Macar Notasyon olarak bilinirHaskell, Macarca Notasyonu teşvik etmek için mi tasarlanmıştır?

debugM 
mapM_ 
mapCE 

. Ama aynı zamanda ben gibi olmayan belirsiz kod yazmak tip sınıfları kullanabilirsiniz:

show 
return 

map gibi fonksiyonlar, niçin tip denetleyicisi map doğru polimorfik versiyonunu almaya izin vermeyin kadar yaygın ve birçok bağlamlarda kullanılan olduğundan , fmap, mapM, mapM_ veya mapCE?

+2

Macarca notasyon, değişken adlarına tür bilgisi ekleme genel fikri değildir; Bu, özellikle, değişken adına * önekleme * tipi bilgileri ile ilgilidir. – jamesdlin

cevap

24

Biraz "Macar notasyonu" var, ama oldukça farklı. Kısacası, Haskell'in tip sistemi, çoğu için ihtiyacı ortadan kaldırır.

map/mapM bir şey düzgün bir örnektir. Bu iki işlev tam olarak aynı kavramı verir, ancak polimorfik olarak temsil edilemez çünkü farkın soyutlanması gerçekten gürültülü olur. Yani bunun yerine bir Macar notası seçiyoruz.

mapM yaptığı tüm monad eklemek, ancak aynı değildir, iki tür

map ::   (a -> b) -> ([a] -> [b]) 
mapM :: Monad m => (a -> m b) -> ([a] -> m [b]) 

Bunlar benzer olan, berrak olmak. yapı aşağıdaki eş anlamlılarını

type Arr a b = a -> b 
type Klei m a b = a -> m b 

yaparken ortaya ve

map ::   Arr a b -> Arr [a] [b] 
mapM :: Monad m => Klei m a b -> Klei m [a] [b] 

olarak not etmek şeyi türlerini yeniden yazmak olduğunu Arr ve Monad m => Klei mson derece benzer şeyler genellikle olmasıdır. Her ikisi de içinde her türlü hesaplama yapabilmemizi sağlayan "kategori" olarak bilinen belirli bir yapı oluştururlar.[0] istediğimiz ne

class Mapping cat where 
    map :: cat a b -> cat [a] [b] 

instance   Mapping (->)  where map = Prelude.map 
instance Monad m => Mapping (Klei m) where map = mapM   -- in spirit anyway 

gibi bir şeyle kategorisinde seçme konusunda soyut etmektir ama yol daha Functor ile liste kısmı üzerinde soyutlayarak elde edilecek orada olduğu ortaya çıktı [1]

class Functor f where 
    map :: (a -> b) -> (f a -> f b) 

instance Functor [] where 
    map = Prelude.map 

instance Functor Maybe where 
    map Nothing = Nothing 
    map (Just a) = Just (f a) 

ve bu yalınlık sağlamak için biz Haskell'ın polimorfizm işlevselliği içine yuvarlayarak yerine kategorisinin fark yaratmak için Macar simgelem.

[0] Klei m'un bir kategori olduğu gerçeği, m'un bir monad olduğunu ve kategori yasalarının tam olarak monad yasaları olmasını sağlar. Özellikle, bu monad yasalarının ne olduğunu hatırlamak için en sevdiğim yol.

[1] Teknik olarak Functor tek yöntemi denir değil mapfmap ama ve belki de sadece map adlandırılabilir başladı. f eklenmiştir, böylece map için tip imzası basit kalır (listelerde uzmanlaşır) ve böylece yeni başlayanlar için biraz daha az korkutucudur. Bu doğru karar olup olmadığı bugün devam eden bir tartışmadır.

+0

Güzel cevap. Ancak, önemli bir noktayı özlüyor gibi görünüyor: Neden Macar Notasyonu * seçtik? “Control.Monad.map” da olabilirdi (Tamam, belki de 'base'deki ad çakışması hariç) – Bergi

+0

Macarca notasyonu kullanabileceğinizi, modül nitelikli isimleri kullanabileceğinizi veya polimorfizmi kullanabileceğinizi varsayalım. Polymorphism dışarı çıktı, özellikle Haskell'in ilk zamanlarında “Functor” ve “Category” benzeri polimorfların karışmaya çalıştığı yerde kabus olurdu. Haskell çok sayıda nitelikli isimden kaçınma eğilimindedir, bu yüzden Control.Monad.map'da bir sorun olmayacak olsa da, pek çok modül nitelenmemiş olarak ithal edilmeyi amaçlamaktadır. Bu yüzden Macar gösteriminden ayrıldık. –

+0

Mevcut iki kaynaktan bir soyutlama seçtiğimizi anlıyorum. Pragmatizm mi yoksa bir dil sınırlaması yüzünden mi yönlendiriliyor? Mapping (Klei m) gibi örnekler Haskell'de (uzantılarla) tanımlanabilir mi? – sevo

7

Sizin varsayımınız bunların hepsinin kabaca aynı şeyi yapmasıdır - yapmazlar. map ve fmap hemen hemen aynı işleve sahiptir - map sadece [] functor (tarihsel nedenlerden dolayı, ya da yeni başlayanlar daha az kafa karıştırıcı tip hataları alacaktır - uzman değilim). Onlar ilgili gibi görünebilir ne yapıyoruz ederken, farklı şeyler yapıyoruz - diğer taraftan

mapM ve mapM_ sırasıyla sequence veya sequence_ ardından map gibidir. Bu arada, monoplar için fmap gibi davranan fonksiyon fmap (liftM için özel bir imzayla aynı zamanda), Monad s, tanım olarak Functor s; Bu, şu anda, standart kütüphane tarafından zorlanmadı - yanlış değilse GHC 7.10 ile düzeltilmesi gereken tarihi bir gözetim olduğuna dikkat edin.

Bunları daha önce görmediğim gibi, debugM ve mapCE hakkında ne söyleyeceğimi bilmiyorum.