Çalışan adam için birleştiricilerin açıklaması


93

Birleştirici nedir?

Bu mi "serbest değişkenli bir fonksiyon ya da tanımı" (böylece tarif edildiği gibi)?

Ya da şuna ne dersiniz: John Hughes'un Oklar hakkındaki ünlü makalesine göre, "bir birleştirici, program parçalarından program parçalarını oluşturan bir işlevdir" , bu avantajlıdır çünkü "... birleştiricileri kullanan programcı istenenlerin çoğunu oluşturur her ayrıntıyı elle yazmak yerine otomatik olarak programlayın ". Bunu söylemeye devam ediyor mapve filterbu tür birleştiricilerin iki yaygın örneği.

İlk tanıma uyan bazı birleştiriciler:

İkinci tanıma uyan bazı birleştiriciler:

  • harita
  • filtre
  • katlama / azaltma (muhtemelen)
  • >> =, compose, fmap'den herhangi biri ?????

İlk tanımla ilgilenmiyorum - bunlar gerçek bir program yazmama yardımcı olmaz (beni yanıldığıma ikna edersen +1). Lütfen ikinci tanımı anlamama yardım edin . Harita, filtreleme ve azaltmanın yararlı olduğunu düşünüyorum: daha yüksek bir seviyede programlama yapmama izin veriyorlar - daha az hata, daha kısa ve daha net kod. Kombinatörlerle ilgili özel sorularımdan bazıları:

  1. Harita, filtre gibi daha fazla birleştirici örnekleri nelerdir?
  2. Programlama dilleri genellikle hangi birleştiricileri uygular?
  3. Birleştiriciler daha iyi bir API tasarlamama nasıl yardımcı olabilir?
  4. Etkili birleştiricileri nasıl tasarlarım?
  5. İşlevsel olmayan bir dilde (örneğin, Java) benzer birleştiriciler nelerdir veya bu diller birleştiriciler yerine ne kullanır?

Güncelleme

@CA McCann sayesinde, artık kombinatörleri biraz daha iyi anlıyorum. Ama bir soru hala benim için sorunlu bir nokta:

Kombinatörlerin yoğun kullanımı ile yazılan ve kullanılmayan işlevsel bir program arasındaki fark nedir?

Cevabın, birleştirici ağırlıklı versiyonun daha kısa, daha net ve daha genel olduğundan şüpheleniyorum, ancak mümkünse daha derinlemesine bir tartışmayı takdir ediyorum.

Ayrıca fold, ortak programlama dillerinde karmaşık birleştiriciler için (yani daha karmaşık ) daha fazla örnek ve açıklama arıyorum .


4
Yüksek Dereceli İşlevleri eşleme / filtreleme / katlama olarak değerlendiriyorum ve bunları her zaman kullanıyorum. Hala birleştiricinin ne olduğu hakkında hiçbir fikrim yok.

1
@pst - 5 gün önce kabul ederdim, ancak şimdi John Hughes ile tartışamıyorum
Matt Fenwick

Yanıtlar:


93

İlk tanımla ilgilenmiyorum - bunlar gerçek bir program yazmama yardımcı olmaz (beni yanıldığıma ikna edersen +1). Lütfen ikinci tanımı anlamama yardım edin. Harita, filtreleme ve azaltmanın yararlı olduğunu düşünüyorum: daha yüksek bir seviyede programlama yapmama izin veriyorlar - daha az hata, daha kısa ve daha net kod.

İki tanım temelde aynı şeydir. İlki biçimsel tanıma dayalıdır ve verdiğiniz örnekler ilkel birleştiricilerdir - mümkün olan en küçük yapı taşları. Gerçek bir program yazmanıza yardımcı olabilirler, çünkü onlarla daha sofistike birleştiriciler oluşturabilirsiniz. S ve K gibi birleştiricileri varsayımsal bir "birleştirici bilgisayarın" makine dili olarak düşünün. Elbette gerçek bilgisayarlar bu şekilde çalışmaz, bu nedenle pratikte genellikle perde arkasında başka şekillerde uygulanan daha yüksek düzeyli işlemlere sahip olursunuz, ancak kavramsal temel hala bu üst düzeylerin anlamını anlamak için yararlı bir araçtır. operasyonlar.

Verdiğiniz ikinci tanım daha gayri resmi ve diğer işlevleri çeşitli şekillerde birleştiren üst düzey işlevler biçiminde daha karmaşık birleştiriciler kullanmakla ilgili. Temel yapı taşları yukarıdaki ilkel birleştiriciler ise, onlardan oluşturulan her şeyin bir üst düzey işlev ve aynı zamanda bir birleştirici olduğunu unutmayın. Bununla birlikte, diğer ilkellerin var olduğu bir dilde, işlev olan veya olmayan şeyler arasında bir ayrımınız vardır; bu durumda, bir birleştirici tipik olarak, başka işlevler üzerinde işlem yapmak yerine, diğer işlevleri genel bir şekilde işleyen bir işlev olarak tanımlanır. işleri doğrudan işler.

Harita, filtre gibi daha fazla birleştirici örnekleri nelerdir?

Listelenemeyecek kadar çok! Bunların her ikisi de tek bir değerdeki davranışı tanımlayan bir işlevi, tüm koleksiyondaki davranışı tanımlayan bir işleve dönüştürür. Ayrıca, yalnızca diğer işlevleri dönüştüren , örneğin onları uçtan uca oluşturma veya bağımsız değişkenleri bölme ve yeniden birleştirme gibi işlevlere sahip olabilirsiniz . Tek adımlı işlemleri, koleksiyon üreten veya tüketen yinelemeli işlemlere dönüştüren birleştiricilere sahip olabilirsiniz. Ya da her türlü başka şey, gerçekten.

Programlama dilleri genellikle hangi birleştiricileri uygular?

Bu biraz değişecek. Nispeten az sayıda tamamen jenerik birleştirici vardır - çoğunlukla yukarıda belirtilen ilkel olanlar - bu nedenle çoğu durumda birleştiriciler, kullanılan herhangi bir veri yapısı hakkında biraz farkındalığa sahip olacaktır (bu veri yapıları yine de diğer birleştiricilerden oluşturulmuş olsa bile). tipik olarak bir avuç "tamamen jenerik" birleştirici ve daha sonra birisinin sağlamaya karar verdiği çeşitli özel biçimler vardır. Harita, katlama ve açmanın (uygun şekilde genelleştirilmiş sürümlerinin) isteyebileceğiniz neredeyse her şeyi yapmak için yeterli olduğu çok sayıda saçma durum vardır.

Birleştiriciler daha iyi bir API tasarlamama nasıl yardımcı olabilir?

Tam olarak söylediğiniz gibi, düşük seviyeli ayrıntılar yerine üst düzey operasyonlar ve bunların etkileşim biçimleri açısından düşünerek.

"Her biri için" tarzı döngülerin koleksiyonlar üzerindeki popülaritesini düşünün, bu da bir koleksiyonu listelemenin ayrıntılarını özetlemenize olanak tanır. Bunlar çoğu durumda sadece eşleme / katlama işlemleridir ve bunu bir birleştirici yaparak (yerleşik sözdizimi yerine) mevcut iki döngüyü alıp bunları birden çok şekilde doğrudan birleştirmek gibi şeyler yapabilirsiniz - birini diğerinin içine yerleştirmek, birbiri ardına yapın ve benzeri - bir sürü kodla uğraşmak yerine, sadece bir birleştirici uygulayarak.

Etkili birleştiricileri nasıl tasarlarım?

Öncelikle, programınızın kullandığı verilerde hangi işlemlerin anlamlı olduğunu düşünün. Ardından, bu işlemlerin genel şekillerde anlamlı bir şekilde nasıl birleştirilebileceğini ve işlemlerin tekrar birbirine bağlanan daha küçük parçalara nasıl bölünebileceğini düşünün. Esas olan , doğrudan eylemlerle değil, dönüşümler ve operasyonlarla çalışmaktır . Bazı karmaşık işlevselliği opak bir şekilde yapan ve yalnızca bir tür önceden sindirilmiş sonuç veren bir işleve sahipseniz, bununla yapabileceğiniz pek bir şey yoktur. Nihai sonuçları , birleştiricileri kullanan koda bırakın - sizi A noktasından B noktasına götüren şeyler istersiniz, bir sürecin başlangıcı veya sonu olmasını bekleyen şeyler değil.

İşlevsel olmayan bir dilde (örneğin, Java) benzer birleştiriciler nelerdir veya bu diller birleştiriciler yerine ne kullanır?

Ahahahaha. Sormanız komik, çünkü nesneler ilk etapta gerçekten üst düzey şeylerdir - bazı verileri vardır, ancak aynı zamanda bir dizi işlem taşırlar ve iyi bir OOP tasarımını oluşturan şeylerin çoğu "nesnelerin genellikle veri yapıları değil, birleştiriciler gibi davranır ".

Muhtemelen buradaki en iyi cevap, birleştirici benzeri şeyler yerine, çok sayıda alıcı ve ayarlayıcı yöntemi veya genel alan içeren sınıfları ve çoğunlukla opak, önceden tanımlanmış bir eylem yapmaktan oluşan mantığı kullanmalarıdır.


Mükemmel cevap! Bakalım anlayıp anlamadım - birleştiriciler özel değil, daha ziyade, sürdürülebilir bir yazılım sistemi oluşturmanın ayrılmaz bir parçası mı? Hala gönderiniz bağlamında Hughes'un "program parçaları" ifadesini sindirmeye çalışıyorum.
Matt Fenwick

@Matt Fenwick: Bahsettiğim dönüşümleri / işlemleri ifade etmek için sadece "program parçalarını" kullandığından eminim, özellikle de bu yaklaşımı daha da güçlü bir şekilde vurgulayan "Oklar" dan bahsediyorsanız. Ayrıca, bunun tam olarak bakımı yapılabilir sistemler inşa etmekle ilgili olduğunu söyleyemem - daha çok, oldukça modüler ve belirli bir şekilde ayrıştırılmış ve beraberinde getirdiği faydalar ile sistemler inşa etmekle ilgili.
CA McCann

Kombinatörlerin pratik kullanımı hakkında bilgi almak için iyi kaynaklar biliyor musunuz? Çok teşekkürler!
Matt Fenwick

@Matt Fenwick: Aklıma gelen o kadar özel bir şey yok , üzgünüm. Bununla birlikte, çok işlevsel bir tarzda yazılmış programlar için doğal bir yaklaşım olma eğilimindedir, bu nedenle sadece bunu güçlü bir şekilde teşvik eden dillerle (örn. Haskell veya Clojure) biraz zaman geçirmek ve bu dilde ne kadar temiz ve deyimsel kod yazıldığına bakmak , tarzı hissetmek için oldukça iyi bir yoldur.
CA McCann
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.