Fonksiyonel programlar neden derleme başarısı ile doğruluk arasında bir korelasyona sahiptir?


12

LINQ ile çalışmaya başladığımdan beri 4 yıldır fonksiyonel programlamaya yöneldim. Son zamanlarda, bazı saf fonksiyonel C # kodu yazdım ve ilk elden, fonksiyonel programlar hakkında ne okuduğumu fark ettim - derlediklerinde doğru olma eğilimindedirler.

Neden böyle olduğuna bir parmak koymaya çalıştım ama başaramadım.

Bir tahmin, OO ilkelerini uygularken, işlevsel programlarda bulunmayan bir "soyutlama katmanına" sahip olmanız ve bu soyutlama katmanının, uygulama yanlışken nesneler arasındaki sözleşmelerin doğru olmasını mümkün kılmasıdır.

Bunu düşünen ve fonksiyonel programlamada derleme başarısı ve program doğruluğu arasındaki korelasyonun altında yatan soyut bir sebep ortaya çıkaran oldu mu?


9
Lisp işlevsel bir dildir, ancak konuşmak için derleme zamanı kontrolleri yoktur. Birkaç işlevsel dil için de aynı şey geçerli. Bahsettiğiniz dillerin daha doğru bir karakterizasyonu şu şekildedir: Güçlü biçimsel (en azından Hindley-Milner) tip sistemlere sahip diller.

1
@delnan Lisp'in işlevsel bir programlama dili olduğunu söyleyemem, ancak işlevsel programlama kodu yazmak için kullanılabilir. Lisp lehçesi olan Clojure fonksiyonel bir programlama dilidir
sakisk

2
@Delnan'a katılıyorum. Bu ifade, statik olarak yazılan fonksiyonel programlama dilleri, özellikle Hindley-Milner sistemini kullanan Haskell ile daha ilgilidir. Ana fikir, türleri doğru alırsanız, programınızın doğru olduğuna dair güvenin artması olduğunu düşünüyorum.
sakisk

1
İşlevsel kod, tipik, ana akım OOP kodunuz kadar çok soyutlama ve indirgeye sahip olabilir (daha fazla değilse). Şeytan ayrıntılarda gizlidir - daha az yan etki ve sıfırın olmaması, izlenmesi daha az görünmez durum ve daha az vidalanma şansı anlamına gelir. Aynı ilkeleri ana akım zorunlu dillerinde uygulayabileceğinizi unutmayın, sadece daha fazla iş ve genellikle daha ayrıntılı (örneğin final, her şeye tokat atmak zorunda ).
Doval

1
Değil programın tam cevap ama yazarak olan programın biçimsel doğrulama ham formu. Genel olarak Nesne Odaklı programlar, ikame dikkate alınması gerektiği için karmaşık veya çok basit tip sistemlere sahiptir - çoğu durumda, kolaylık sağlamak için sağlamlaştırılırlar. OTOH ML benzeri sistemler, CH'yi tam olarak kullanabilir, böylece bir prova tipinde kodlayabilir ve derleyiciyi prova denetleyicisi olarak kullanabilirsiniz.
Maciej Piechotka

Yanıtlar:


12

Bu cevabı işleri çok kanıtlayan biri olarak yazabilirim, bu yüzden benim için doğruluk sadece neyin işe yaradığı değil, neyin işe yaradığını ve kanıtlanması kolay.

Pek çok anlamda fonksiyonel programlama, zorunlu programlamaya göre daha kısıtlayıcıdır. Sonuçta, hiçbir şey C'de bir değişkeni asla mutasyona uğratmanızı engellemez! Aslında, FP dillerindeki özelliklerin çoğu, sadece birkaç temel özellik açısından konuşmak için basittir. Hepsi hemen hemen lambdas, fonksiyon uygulaması ve desen eşleştirme kaynar!

Ancak, pipere önceden ödeme yaptığımızdan, başa çıkmak için çok daha az şeyimiz var ve işlerin nasıl yanlış gidebileceğine dair çok daha az seçeneğimiz var. Eğer 1984 hayranıysanız, özgürlük gerçekten köleliktir! Bir program için 101 farklı hileci kullanarak, bu 101 şeyden herhangi biri olabilir gibi şeyler hakkında mantık yürütmeliyiz! Görünen o ki bunu yapmak gerçekten zor :)

Kılıç yerine güvenlik makasıyla başlarsanız koşma nispeten daha az tehlikelidir.

Şimdi sorunuza bakıyoruz: Tüm bunlar "derliyor ve çalışıyor!" fenomen. Bunun büyük bir kısmının neden kodu kanıtlamanın kolay olmasının nedeni olduğunu düşünüyorum! Sonuçta, yazılım yazarken doğru olduğuna dair gayri resmi bir kanıt oluşturuyorsunuz. Bu nedenle, doğal el yıkama kanıtlarınız ve derleyicilerin kendi doğruluk kavramını (daktilo kontrol) kapladığı şey oldukça fazladır.

Aralarına özellikler ve karmaşık etkileşimler ekledikçe, tür sistemi tarafından kontrol edilmeyen şeyler artar. Ancak, resmi olmayan kanıtlar oluşturma yeteneğiniz gelişiyor gibi görünmüyor! Bu, ilk muayenenizde kayabilecek ve daha sonra yakalanması gereken daha fazla şey olduğu anlamına gelir.


1
Cevabınızı beğendim ama OP'nin sorusuna nasıl cevap verdiğini göremiyorum
sakisk

1
@faif Cevabımı genişlettim. TLDR: herkes bir matematikçi.
Daniel Gratzer

"Bir program için 101 farklı düzgün hileci kullanarak, bu 101 şeyden herhangi biri olabilir gibi şeyler hakkında mantıklı olmalıyız!": Mutasyonla programlamak için dahi olmanız gereken bir yerde okudum, çünkü kafanızda çok fazla bilgi.
Giorgio

12

programlamada derleme başarısı ve program doğruluğu arasındaki korelasyonun altında yatan soyut neden nedir?

Değişken Devlet.

Derleyiciler olayları statik olarak kontrol eder. Programınızın iyi biçimlendirildiğinden emin olurlar ve tip sistemi, doğru yerlerde doğru değerlere izin verilmesini sağlamak için bir mekanizma sağlar. Yazı sistemi aynı zamanda doğru türde semantiğe doğru yerde izin verilmesini sağlamaya çalışır.

Programınız durumu tanıtır getirmez, bu ikinci kısıtlama daha az kullanışlı hale gelir. Sadece doğru noktalardaki doğru değerler için endişelenmekle kalmaz, aynı zamanda programınızın keyfi noktalarındaki bu değeri de hesaba katmanız gerekir. Kodunuzun söz konusu durumla birlikte değişen semantiğini hesaba katmanız gerekir.

İşlevsel programlamayı iyi yapıyorsanız, değiştirilemez (veya çok az) durum yoktur.

Burada nedensellik hakkında bazı tartışmalar var - derleyici sonra devlet olmayan programlar daha sık çalıştığı için derleyici daha fazla hata yakalayabilir veya bu programlama tarzı daha az hata ürettiği için derlemeden sonra devletsiz programlar daha sık çalışırsa.

Muhtemelen deneyimlerimin her ikisinin bir karışımı.


2
“Muhtemelen her ikisinin de tecrübelerimin bir karışımı.”: Aynı deneyime sahibim. Statik yazım, zorunlu bir dil (örn. Pascal) kullanırken de derleme zamanında hataları yakalar. FP'de değişebilirliğin önlenmesi ve daha açıklayıcı bir programlama stilinin kullanılması, kod hakkında akıl yürütmeyi kolaylaştırır. Bir dil her ikisini de sunarsa, her iki avantajı da elde edersiniz.
Giorgio

7

Basitçe ifade etmek gerekirse, kısıtlamalar, şeyleri bir araya getirmenin daha az doğru yolu olduğu anlamına gelir ve birinci sınıf işlevler, döngü yapıları gibi şeyleri hesaplamayı kolaylaştırır. Döngüyü bu yanıttan alın, örneğin:

for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
    String string = iterator.next();
    if (string.isEmpty()) {
        iterator.remove();
    }
}

Bu, bir öğeyi yineleme sırasında koleksiyondan bir öğeyi kaldırmak için Java'da güvenli bir zorunluluk yoludur. Çok yakın görünen ama yanlış olan birçok yol var. Bu yöntemin farkında olmayan kişiler, bazen bir kopyadan yineleme gibi, sorunu önlemek için kıvrımlı yollardan geçer.

Bu jenerik yapmak çok zor değil, bu yüzden sadece koleksiyonlarından daha fazlası üzerinde çalışacak Strings, ancak birinci sınıf işlevler olmadan yüklemi (içindeki koşul if) değiştiremezsiniz, bu nedenle bu kod kopyalanıp yapıştırılır ve biraz değiştirildi.

Eğer yüklemi bir parametre olarak geçirme yeteneği veren birinci sınıf işlevleri birleştirmezseniz , bunu yapmazsanız çok can sıkıcı hale getiren ve filterbu Scala kodunda olduğu gibi basit yapı taşlarına sahip olursunuz. aynı şeyi yapar:

list filter (!_.isEmpty)

Şimdi, Scala durumunda derleme zamanında tür sisteminin sizin için neyi kontrol ettiğini düşünün, ancak bu kontrolleri ilk kez çalıştırdığınızda dinamik tür sistemleri tarafından da yapılır:

  • listfilteryöntemi destekleyen bir tür , yani bir koleksiyon olmalıdır.
  • Öğelerinin bir boole döndüren yöntemi listolmalıdır isEmpty.
  • Çıktı, aynı tip elemanlara sahip (potansiyel olarak) daha küçük bir koleksiyon olacaktır.

Bu şeyler kontrol edildikten sonra, programcının vidalaması için başka hangi yollar kalır? !Son derece açık bir test senaryosu hatasına neden olan yanlışlıkla unuttum . Bu hemen hemen mevcut tek hata, ve ben sadece ters koşul için test edilen koddan doğrudan çeviri çünkü ben bunu yaptım.

Bu desen tekrar tekrar tekrarlanır. Birinci sınıf işlevler, şeyleri hassas semantiklerle yeniden kullanılabilir küçük yardımcı programlara dönüştürmenize izin verir, değişmezlik gibi kısıtlamalar size bunu hızlandırır ve bu yardımcı programların parametrelerini kontrol etmek, onları sıkıştırmak için çok az alan bırakır.

Tabii ki, bu programcıya basitleştirici fonksiyonun filterzaten var olduğunu bilmesi ve onu bulabilmesi veya kendiniz yaratmanın faydasını tanımasına bağlıdır. Bunu sadece kuyruk özyineleme kullanarak kendiniz her yerde uygulamaya çalışın ve zorunlu versiyonla aynı karmaşıklık teknesinde geri döndünüz, sadece daha da kötüsü. Eğer sırf yapabilirsiniz çok basit bir şekilde yazma, basit sürüm açıktır anlamına gelmez.


"Bu şeyler kontrol edildikten sonra, programcı için berbat etmek için başka hangi yollar kalıyor?": Bu, bir şekilde (1) statik yazım + (2) fonksiyonel stilin şeyleri vidalamak için daha az yol bıraktığı deneyimimi doğrular. Sonuç olarak doğru programı daha hızlı alıyorum ve FP kullanırken daha az birim testi yazmam gerekiyor.
Giorgio

2

İşlevsel programlama derlemesi ile çalışma zamanı doğruluğu arasında önemli bir ilişki olduğunu düşünmüyorum. Statik olarak yazılan derleme ve çalışma zamanı doğruluğu arasında bir korelasyon olabilir, çünkü döküm yapmıyorsanız en azından doğru türlere sahip olabilirsiniz.

Tanımladığınız gibi, başarılı derlemeyi çalışma zamanı türü doğruluğu ile bir şekilde ilişkilendirebilecek programlama dili yönü statik yazımdır ve o zaman bile yalnızca tür denetleyicisini yalnızca çalışma zamanında iddia edilebilecek dökümlerle zayıflatmıyorsanız ( güçlü yazılan değerler veya yerler, örneğin Java veya .Net) veya hiç değil (tür bilgilerinin kaybolduğu veya zayıf yazılan ortamlarda, örneğin C ve C ++).

Bununla birlikte, işlevsel programlama kendi başına paylaşılan verilerden ve değişebilir durumlardan kaçınma gibi başka şekillerde yardımcı olabilir.

Her iki yönün birlikte doğrulukta önemli bir korelasyonu olabilir, ancak hiçbir derleme ve çalışma zamanı hatasına sahip olmanın, programda yapması gerekeni yaptığı ve hızlı başarısız olduğu gibi, daha geniş anlamda doğruluk hakkında hiçbir şey söylemediğini bilmelisiniz. geçersiz giriş veya kontrol edilemeyen çalışma zamanı hatası. Bunun için iş kurallarına, gereksinimlere, kullanım senaryolarına, iddialara, birim testlerine, entegrasyon testlerine vb. İhtiyacınız vardır. Sonunda, en azından bence, fonksiyonel programlama, statik yazım veya her ikisinden çok daha fazla güven sağlarlar.


Bu. Bir programın doğruluğu başarılı derleme ile değerlendirilemez. Bir derleyici, programın özelliklerine katkıda bulunan her kişinin sık sık çelişen ve yanlış gereksinimlerini anlayabiliyorsa, başarılı derleme doğruluk olarak değerlendirilebilir. Ama bu efsanevi derleyicinin bir programcıya ihtiyacı olmaz! Bir olsa da biraz daha yüksek zorunlu programlara karşı fonksiyonel için derleme ve doğruluğu arasındaki genel ilişki, ben temelde alakasız düşünüyorum toplam doğruluğu kararın böyle küçük bir parçasıdır
Ürdün Rieger

2

Yöneticiler için açıklama:

İşlevsel bir program, her şeyin bağlı olduğu büyük bir makine, tüpler, kablolar gibidir. [Araba]

Prosedürel bir program, küçük bir makine içeren odalara sahip, kısmi ürünleri kutulara depolayan, başka yerlerden kısmi ürünler alan bir bina gibidir. [Bir fabrika]

Böylece fonksiyonel makine zaten birbirine uyduğunda: bir şey üretmek zorunda kalır. Bir prosedür kompleksi çalışırsa, işleyişi garanti etmeyen belirli etkilere, kaosa girmiş olabilirsiniz. Her şeyin doğru bir şekilde entegre edilmesinin bir kontrol listesine sahip olsanız bile, garantilerin verilmesi zor olan çok fazla durum, durum (etrafta kısmi ürünler, taşan kovalar, eksik) var.


Ancak ciddi olarak, prosedürel kod, istenen sonucun anlambilimini fonksiyonel kod kadar belirtmez. Prosedürel programcılar, durumsal kod ve verilerle daha kolay uzaklaşabilir ve bir şeyi yapmanın birkaç yolunu (bazıları kusurlu) tanıtabilir. Tipik olarak yabancı veriler oluşturulur. Sorun daha karmaşık hale geldiğinde fonksiyonel programcılar daha uzun sürebilir mi?

Güçlü bir yazım işlevsel dili hala daha iyi veri ve akış analizi yapabilir. Prosedürel bir dille, bir programın amacı genellikle programın dışında, resmi bir doğruluk analizi olarak tanımlanmalıdır.


1
Daha iyi anoloji: Fonksiyonel programlama, müşterileri olmayan bir yardım masası gibidir - her şey harikadır (amacı veya verimliliği sorgulamadığınız sürece).
Brendan

@Brendan otomobil fabrikası böyle kötü bir benzetme oluşturmuyor. İşlevsel bir dilde (küçük ölçekli) programların neden çalışma olasılığının daha yüksek olduğunu ve "fabrikadan" daha az hataya açık olduğunu açıklamaya çalışır. Ancak OOP'un kurtarılması için bir fabrika birkaç şey üretebilir ve daha büyüktür. Karşılaştırmanız uygun; FP'nin ne sıklıkta paralellik gösterebildiğini ve optimize edebildiğini duyar ama aslında (pun yok) yavaş sonuçlar verir. Hala FP'ye tutunuyorum.
Joop Eggen

Ölçekli işlevsel programlama bir en.wikipedia.org/wiki/Spherical_cow için oldukça iyi çalışır .
Den Den

@Ben büyük ölçekli bir FP projesinde hiçbir fizibilite probleminden korkmam. Hatta seviyorum. Genellemenin bir sınırlaması vardır. Ama bu son ifade de bir genelleme olduğu için ... (küresel inek için teşekkürler)
Joop Eggen
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.