Fonksiyonel programlama problemler ve çözümler arasındaki 'temsili boşluğu' artırır mı? [kapalı]


18

Makine dili (örn. 0110101000110101) Bilgisayar dilleri genellikle daha yüksek soyutlama biçimlerine dönüştüğünden, genellikle bir soruna uygulandığında kodu anlamayı kolaylaştırır. Birleştirici, makine kodu üzerinde bir soyutlama, C, birleştirici üzerinde bir soyutlama vb.

Nesne yönelimli tasarım, nesneler açısından bir problemi modellememize izin vermede çok iyi görünmektedir, örneğin, bir üniversite ders kayıt sistemi problemi bir Coursesınıf, bir Studentsınıf vb. İle modellenebilir . Sonra, çözümü yazdığımızda OO dilinde, sorumluluk alan ve tasarım için, özellikle de kodu modüle etmek için genellikle yardımcı olan benzer sınıflarımız var. Eğer bu problemi bir OO yöntemiyle çözen 10 bağımsız takıma verirsem, genellikle 10 çözüm ortak problem ile ilgili sınıflara sahip olacaktır. Bu sınıfların birleşmesine ve etkileşimlerine girmeye başladığınızda çok fazla farklılık olabilir, bu nedenle "sıfır temsili boşluk" diye bir şey yoktur.

Fonksiyonel Programlama ile ilgili deneyimim çok sınırlıdır (gerçek dünya kullanımı yoktur, sadece Hello World tipi programlar). Bu tür dillerin FP çözümlerini OO dillerinin yaptığı gibi sorunlara (düşük temsili bir boşlukla) kolayca eşleştirmeye nasıl izin verdiğini göremiyorum.

FP'nin eşzamanlı programlama açısından avantajlarını anlıyorum. Ama bir şey mi kaçırıyorum, yoksa FP temsili bir boşluğu azaltmakla ilgili değil (çözümleri daha kolay anlaşılır kılıyor)?

Bunu sormanın başka bir yolu: Aynı gerçek dünya sorununu çözen 10 farklı takımın FP kodunun ortak bir yanı var mı?


Vikipedi'den Soyutlama (bilgisayar bilimi) (benimkini vurgulayın):

Fonksiyonel programlama dilleri yaygın sergileyen fonksiyonlarla ilgili soyutlamalar gibi lamda soyutlamaların (bazı değişkenin bir fonksiyonu bir terim yapma), yüksek mertebeden fonksiyonlarının (parametreler fonksiyonlar), braket soyutlama (değişkenin bir fonksiyonu bir terim yapma).

Temsili boşluk potansiyel olarak arttırılabilir, çünkü [bazı] gerçek dünya sorunları bu tür soyutlamalarla kolayca modellenmez.


Temsili boşluğun azaldığını görmenin bir başka yolu, çözüm öğelerini soruna geri döndürmektir. 0Var ve 1makine kodu s ise, geri iz çok zordur Studentsınıf iz geri kolaydır. Tüm OO sınıfları problem alanına kolayca ulaşmaz, ancak birçoğu yapar.

FP soyutlamalarının problem alanının hangi kısmını çözdüklerini bulmak için her zaman açıklamaya gerek yoktur ( matematik problemleri dışında )?Tamam - bu konuda iyiyim. Daha birçok örneğe baktıktan sonra, FP soyutlamalarının sorunun veri işlemede ifade edilen kısımları için ne kadar açık olduğunu görüyorum.


İlgili bir soruya kabul edilen cevap UML bir Fonksiyonel programı modellemek için kullanılabilir mi? - "Fonksiyonel programcıların diyagramlar için fazla bir kullanımı yoktur." UML olup olmadığını gerçekten umursamıyorum, ancak FP soyutlamalarının anlaşılması / iletişiminin kolay olmasını merak ediyorum, yaygın olarak kullanılan diyagramlar yoksa (bu cevabın doğru olduğunu varsayarak). Yine, FP kullanım / anlama seviyem önemsizdir, bu yüzden basit FP programlarında şemalara gerek olmadığını anlıyorum.

OO tasarımı, her birinde kapsülleme (erişim kontrolü, bilgi gizleme) ile işlev / sınıf / paket düzeyinde soyutlamaya sahiptir, bu da karmaşıklığı yönetmeyi kolaylaştırır. Bunlar problemden çözüme ve daha kolay geri dönmeye izin veren unsurlardır.


Birçok cevap, analiz ve tasarımın FP'de OO'ya benzer şekilde nasıl yapıldığından bahsediyor, ancak kimse şimdiye kadar üst düzey bir şeyden bahsedemiyor (paul bazı ilginç şeyler gösterdi, ancak düşük seviyeli). Dün çok fazla Google Çalışması yaptım ve bazı ilginç tartışmalar buldum. Aşağıdakiler Simon Thompson'un (2004) (Vurgu madeni) Fonksiyonel Programları Yeniden Düzenleme'den alınmıştır.

Nesneye yönelik bir sistem tasarlanırken, tasarımın programlamadan önce olacağı düşünülmektedir. Tasarımlar, Eclipse gibi araçlarda desteklenen UML gibi bir sistem kullanılarak yazılacaktır. Yeni başlayan programcılar BlueJ gibi sistemleri kullanarak görsel tasarım yaklaşımını iyi öğrenebilirler. Fonksiyonel programlama için benzer bir metodoloji üzerindeki çalışmalar FAD: Fonksiyonel Analiz ve Tasarım'da rapor edilmiştir , ancak çok az çalışma vardır. Bunun birkaç nedeni olabilir.

  • Mevcut fonksiyonel programlar tasarım gerektirmeyen bir ölçektir. Birçok işlevsel program küçüktür, ancak Glasgow Haskell Derleyicisi gibi diğerleri önemlidir.

  • Fonksiyonel programlar doğrudan uygulama alanını modellemekte, böylece tasarımı ilgisiz hale getirmektedir. İşlevsel diller çeşitli güçlü soyutlamalar sağlarken, bunların gerçek dünyayı modellemek için gereken tüm ve sadece soyutlamaları sağladığını iddia etmek zordur.

  • Fonksiyonel programlar gelişen bir dizi prototip olarak oluşturulmuştur.

Gelen Doktora tezi, yukarıda değinilen , Analiz ve tasarım yöntemleri (ADM) kullanmanın yararları paradigmalar bağımsız özetlenmiştir. Ancak, ADM'lerin uygulama paradigmasına uyması gerektiği konusunda bir tartışma yapılmıştır. Yani, OOADM en iyi OO programlama için çalışır ve FP gibi başka bir paradigmaya iyi uygulanmaz. İşte temsili boşluk dediğim şeyleri açıkladığını düşünüyorum büyük bir alıntı:

yazılım geliştirme için hangi paradigmanın en iyi desteği sağladığı konusunda uzun süre tartışılabilir, ancak sorun tanımından uygulama ve teslimata kadar tek bir paradigma içinde kaldığında en doğal, verimli ve etkili geliştirme paketini elde eder.

İşte FAD tarafından önerilen diyagramlar kümesi:

  • Bir işlevi uygulamasında kullandığı işlevlerle sunan işlev bağımlılık diyagramları;
  • tipler için aynı hizmeti sağlayan tip bağımlılık diyagramı; ve,
  • sistemin modül mimarisinin görünümlerini sunan modül bağımlılık diyagramları.

Bir futbol (futbol) ligi ile ilgili veri üretimini otomatikleştiren bir sistem olan FAD tezinin 5.1 bölümünde bir vaka çalışması var. Gereksinimler% 100 işlevseldir, örn. Futbol maç sonuçları, lig tabloları, puanlama tabloları, katılım tabloları, oyuncuları takımlar arasında aktarma, yeni sonuçlardan sonra verileri güncelleme, vb. FAD, fonksiyonel olmayan gereksinimleri çözmek için nasıl çalıştığından bahsedilmez , "yeni işlevselliğe minimum maliyetle izin verilmesi gerektiğini" belirtmek dışında, neredeyse imkansız olan bir şey.

Ne yazık ki, FAD dışında, FP için önerilen modelleme dilleri (görsel) için modern referanslar görmüyorum. UML başka bir paradigma, bu yüzden unutmalıyız.


1
Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
maple_shaft

Yanıtlar:


20

Temel veriler hemen hemen her paradigmada aynı şekilde yapılandırılmıştır. Bir zorunda gidiyoruz Studentbir, Coursebir nesne, bir yapı, bir kayıt ya da her ne olsun, vb. OOP ile fark, verilerin nasıl yapılandırıldığı değil, işlevlerin nasıl yapılandırıldığıdır.

Aslında fonksiyonel programları bir problem hakkındaki düşüncelerime çok daha yakın buluyorum. Örneğin, bir öğrencinin bir sonraki dönem için programını planlamak için, bir öğrencinin tamamladığı derslerin listesi, bir öğrencinin lisans programındaki dersler, bu dönem sunulan dersler, bir öğrencinin ön koşullarını tamamladığı dersler, çatışma vb.

Aniden, hangi sınıfın tüm bu listeleri oluşturması ve saklaması gerektiği belli değil. Hatta bu listelerin karmaşık kombinasyonları olduğunda. Ancak, gereken tek sınıf seçin.

FP'de, öğrenciyi ve ders listesini alan ve filtrelenmiş ders listesini döndüren işlevler yazarsınız. Tüm bu işlevleri bir modülde birlikte gruplayabilirsiniz. Bir sınıf ya da başka bir sınıfla birleştirmek zorunda değilsiniz.

Böylece veri modelleriniz, OOP programcılarının, diğer sınıfların kombinasyonları üzerinde çalışan işlevler koymak için uygun yerler sağlamaktan başka bir amacı olmayan sınıflarla kirlenmeden önce, modellerini nasıl düşündüklerine benziyor. OOP'da CourseStudentFilterListher zaman ihtiyaç duyduğunuz garip veya benzer sınıflar yok , ancak başlangıç ​​tasarımında asla düşünmeyin.


5
@BenAaronson benim deneyimlerimdeki sorun, o zaman bir öğrenci ile ilgili herhangi bir fonksiyonun Öğrenci sınıfına eklenmesi ve sorumlulukları, StudentCourseFiltererişleri yönetilebilir tutmak için tanıtmak gerekene kadar büyüyüp büyümesidir
AlexFoxGill

3
@Den Hibrit yaklaşımların avantajları vardır. Bununla birlikte, ayrımın yapay olduğu doğru değildir. Scala'nın OOP ve FP'ye uyması için yapması gereken birçok taviz var (daha az güçlü tür çıkarımı birdir. Karmaşıklık başka bir şeydir: evet, OOP ve FP'yi karıştıran bir dil daha karmaşık olma eğilimindedir - "kullanımı zor" ve anlayın "- iki uçtaki saf kardeşlerinden birinden daha fazla).
Andres

3
@Den Ayrıca bkz. Erik Meijer'in hibrit yaklaşıma ve tam "köktendinci" FP'ye gitme iddiasında bulunan "Çoğunlukla Fonksiyonel" programlama çalışmıyor ".
Andres

4
@Den Açıkladığınız popülerlik, korkarım, bir tarih kazası. Scala'yı işte kullanıyorum ve FP ve OOP'yi karıştırma girişimi nedeniyle karmaşık bir canavar. Haskell gibi gerçek bir FP diline geçmek temiz bir nefes gibi geliyor - ben de akademik açıdan konuşmuyorum!
Andres

3
@Den Bu işlevlerin ne yaptığını söyleyemem. Bununla birlikte, FP'deki ilk işlevin bir sıralama mı yoksa bir filtre mi olduğunu söyleyebilirim, filtre veya sıralama olarak adlandırılır , değil func(tıpkı adını verdiğiniz IFiltergibi). Genel olarak, FP içinde ne ararsan ediyorum funcya fzaman ya sortya filtergeçerli bir seçimdir! Örneğin, funcparametre olarak üst düzey bir işlev yazarken .
Andres

10

Yıllar önce Java dersimi aldığımda, çözümlerimizi tüm sınıfa göstermemiz bekleniyordu, bu yüzden insanların nasıl düşündüklerini görmeliydim; sorunları mantıksal olarak nasıl çözdüklerini. Çözümlerin üç veya dört ortak çözüm etrafında kümelenmesini bekledim. Bunun yerine, 30 öğrencinin sorunu 30 farklı şekilde çözdüğünü izledim.

Doğal olarak, yeni başlayan programcılar deneyim kazandıkça, ortak yazılım modellerine maruz kalacaklar, bu kalıpları kodlarında kullanmaya başlayacaklar ve sonra çözümleri birkaç optimal strateji etrafında birleşebilirler. Bu kalıplar, deneyimli geliştiricilerin iletişim kurabileceği teknik bir dil oluşturur.

Fonksiyonel programlamanın temelini oluşturan teknik dil matematiktir . Buna göre, fonksiyonel programlama kullanarak çözülmeye en uygun problemler aslında matematik problemleridir. Matematiğe göre, toplama ve çıkarma gibi iş çözümlerinde göreceğiniz matematik türünden bahsetmiyorum. Aksine, Math Overflow'da görebileceğiniz matematik türünden veya Orbitz'in arama motorunda (Lisp'de yazılmıştır) görebileceğiniz matematik türünden bahsediyorum.

Bu yönelim, gerçek dünyadaki programlama problemlerini çözmeye çalışan fonksiyonel programcılar için bazı önemli sonuçlara sahiptir:

  1. İşlevsel programlama zorunlu olandan daha bildiricidir; öncelikle bilgisayara nasıl yapılacağını değil, ne yapacağını söylemekle ilgilidir.

  2. Nesneye yönelik programlar genellikle yukarıdan aşağıya doğru oluşturulur. Bir sınıf tasarımı oluşturulur ve ayrıntılar doldurulur. İşlevsel programlar, alt düzeyden, daha üst düzey işlevlerle birleştirilen küçük, ayrıntılı işlevlerden başlayarak oluşturulur.

  3. Fonksiyonel programlama, karmaşık mantığın prototipini oluşturmak, organik olarak değişebilen ve gelişebilen esnek programlar oluşturmak ve ilk tasarımın belirsiz olduğu yazılımlar oluşturmak için avantajlara sahip olabilir.

  4. Nesneye yönelik programlar, iş alanları için daha uygun olabilir, çünkü sınıflar, nesneler arasındaki mesajlar ve yazılım kalıpları, iş alanıyla eşleşen, iş zekasını yakalayan ve belgeleyen bir yapı sağlar.

  5. Tüm pratik yazılımlar yan etkiler (G / Ç) ürettiğinden, tamamen işlevsel programlama dilleri, matematiksel olarak saf kalırken (monadlar) bu yan etkileri üretmek için bir mekanizma gerektirir.

  6. Fonksiyonel programlar, matematiksel yapıları nedeniyle daha kolay kanıtlanabilir. Haskell'in tip sistemi, çoğu OO dilinin bulamadığı şeyleri derleme zamanında bulabilir.

Ve bunun gibi. Bilgi işlemdeki pek çok şeyde olduğu gibi, nesne yönelimli diller ve işlevsel diller farklı ödünleşmelere sahiptir.

Bazı modern OO dilleri, kullanışlı fonksiyonel programlama kavramlarından bazılarını benimsemiştir, böylece her iki dünyanın da en iyisini elde edebilirsiniz. Linq ve onu desteklemek için eklenen dil özellikleri buna iyi bir örnektir.


6
@thepacker: Fonksiyonel programlamada durumunuz var. Yalnızca gösterim farklıdır: OOP'ta değişken değişkenler kullanırken işlevsel programlamada, programın bunları incelemesi gerektiğinde anında oluşturulan sonsuz durum akışlarını kullanabilirsiniz. Ne yazık ki, durum değişebilir durumlarla tanımlanır, sanki değişebilen durum durumu temsil etmenin tek yolu gibi. Sonuç olarak, birçok kişi değişken değişkenleri olmayan bir programlama dilinin durumu modelleyemeyeceğine inanmaktadır.
Giorgio

12
"Buna göre, fonksiyonel programlama kullanarak çözmek için en uygun problemler aslında matematik problemleridir.": Bu ifadeye katılmıyorum (ayrıca önceki yorumuma bakın), en azından neden doğru veya ne olması gerektiğini görmüyorum aslında. Bir dizin yapısını bir matematik problemi olarak gezdirebilir ve özyinelemeli bir işlevle uygulayabilirsiniz, ancak müşteri kaynak kodunu görmediğinden, dosya sisteminde bir yerde dosya bulma gibi pratik bir sorunu çözersiniz. Matematik ve matematik dışı problemler arasında böyle bir ayrımı yapay buluyorum.
Giorgio

5
+1, ancak 2. ve 4. noktalarda satılmıyorum. Yukarıdan aşağıya bir sorunun üstesinden gelmekle başlayan ve her şeyin birbirine nasıl uyduğunu görmek için tüm türleri ve işlemleri tanımlayarak başlayan çok sayıda Haskell öğretici ve blog yayını gördüm. her değer ve işlev tanımını tanımsız bırakarak (iyi, bir istisna atma olarak tanımlanmış). Bana öyle geliyor ki, Haskell programcıları sorunu daha kapsamlı bir şekilde modelleme eğilimindedir çünkü anlambilim uğruna önemsiz türler eklemeye daha eğilimlidirler - örneğin SafeStringHTML'den kaçan dizeleri temsil etmek için bir tür eklemek - ve genellikle daha fazla takip etmek Etkileri.
Doval

4
"Fonksiyonel programlama kullanarak çözmek için en uygun problemler aslında matematik problemleridir." Bu sadece doğru değil. Monad kavramının kategori teorisinden gelmesi, matematiksel görevlerin işlevsel diller için en doğal / en uygun alan olduğu anlamına gelmez. Bunun anlamı, güçlü yazılan fonksiyonel dillerde yazılmış kodun matematik kullanımı ile ilgili tanımlanabileceği, analiz edilebileceği ve gerekçelendirilebileceği anlamına gelir. Bu güçlü bir ekstra özellik, Haskell "Barbie Horse Adventures" yazmayı durduran bir şey değil.
itsbruce

6
@itsbruce Barbie At Maceraları, en yüksek kalibrenin ciddi bir matematiksel simülasyonudur, FP'yi, insanları ikna eden çeşitli olası gerçek dünya ortamlarında farklı bir gerçek dünya ortamında, Barbie'nin saçlarının ayrı bir dönemde fiziksel olarak parıltısını tanımlayan matrisler gibi aşırı karmaşık sayısal projeksiyonlara bağlar. günlük iş problemi kodlarıyla ilgisiz olarak tamamen reddeder.
Jimmy Hoffa

7

Önemli bulduğum ve diğer cevaplarda ele alınmayan bir yönü vurgulamak istiyorum.

Her şeyden önce, sorunları ve çözümleri arasındaki temsili boşluğun, arka planlarına ve daha aşina oldukları kavramlara göre programcının zihninde daha fazla olabileceğini düşünüyorum.

OOP ve FP verilere ve operasyonlara iki farklı perspektiften bakarlar ve Robert Harvey'in zaten işaret ettiği gibi farklı ödünleşimler sağlarlar.

Farklı olmalarının önemli bir yönü, yazılımınızı genişletmelerine izin vermeleridir.

Veri türlerinin bir koleksiyonunun ve bir işlem koleksiyonunun olduğu durumu göz önünde bulundurun, örneğin farklı görüntü formatlarınız var ve görüntüleri işlemek için bir algoritma kütüphanesi tutuyorsunuz.

İşlevsel programlama, yazılımınıza yeni işlemler eklemenizi kolaylaştırır: kodunuzda yalnızca yerel bir değişikliğe ihtiyacınız vardır, yani farklı giriş veri biçimlerini işleyen yeni bir işlev eklersiniz. Öte yandan, yeni formatlar eklemek daha karmaşıktır: daha önce uyguladığınız tüm işlevleri değiştirmeniz gerekir (yerel olmayan değişiklik).

Nesne yönelimli yaklaşım bunun için simetriktir: her veri türü tüm işlemlerin kendi uygulamasını gerçekleştirir ve çalışma zamanında doğru uygulamayı seçmekten sorumludur (dinamik dağıtım). Bu, yeni bir veri türü (örn. Yeni bir görüntü formatı) eklemeyi kolaylaştırır: sadece yeni bir sınıf ekler ve tüm yöntemlerini uygularsınız. Öte yandan, yeni bir işlem eklemek, o işlemi sağlaması gereken tüm sınıfları değiştirmek anlamına gelir. Birçok dilde bu bir arabirimi genişleterek ve onu uygulayan tüm sınıfları uyarlayarak yapılır.

Bu farklı genişletme yaklaşımı, OOP'nin, işlem kümesinin, bu işlemlerin üzerinde çalıştığı veri türleri kümesinden daha az değiştiği bazı sorunlar için daha uygun olmasının nedenlerinden biridir. Tipik bir örnek GUI'lerdir: Tüm widget'ları uygulamaları gerektiğini operasyonların sabit bir dizi (var paint, resize, moveve benzeri) ile genişletmek istediğiniz widget bir koleksiyon.

Yani, bu boyuta göre, OOP ve FP kodunuzu düzenlemenin sadece iki speküler yoludur. Bkz. SICP , özellikle Bölüm 2.4.3, Tablo 2.22 ve Mesaj iletimi paragrafı .

Özetleme: OOP'de işlemleri düzenlemek için verileri, FP'de verileri düzenlemek için kullanırsınız. Her yaklaşım, bağlama göre daha güçlü veya daha zayıftır. Genel olarak, bu ikisinin hiçbirinin problem ve çözüm arasında daha yüksek bir temsili boşluğu yoktur.


1
Aslında, Ziyaretçi Deseni (OOP'ta) FP için söylediğinizle aynı gücü verir. Yeni sınıflar eklemeyi zorlaştırırken yeni işlemler eklemenizi sağlar. Aynı şeyi FP'de yapıp yapamayacağınızı merak ediyorum (örneğin, işlemler yerine yeni formatlar ekleme).
Euphoric

1
Görüntü işleme senaryosu bunun en iyi örneği gibi görünmüyor. Şüphesiz görüntüleri bir iç biçime dönüştürür ve her görüntü türü için tüm görüntü işleme öğelerinizin ayrı uygulamalarını yazmak yerine bunu işler misiniz?
Hey

1
@Giorgio belki bu bölümden amaçlanan anlamını alamıyorum: "yeni biçimler eklemek daha çok işin içine giriyor: zaten uyguladığınız tüm işlevleri değiştirmeniz gerekiyor."
Hey

2
Hey Giorgio muhtemelen İfade Sorunu'ndan söz ediyor . "Yeni biçimler eklemek", "bir veri türüne yeni kurucular (diğer bir deyişle" durumlar ") eklemek anlamına gelir.
Andres

1
@Eophoric: Ayrıntılara bakmadım, ancak ziyaretçi modelinin FP karşılığı Other, veri türünüzde bir varyant / yapıcı ve diğer durumu işlemek için tüm işlevlere iletilecek ekstra bir işlev parametresi içermelidir . Tabii ki, OOP çözümüne (dinamik sevkiyat) göre garip / daha az doğaldır. Aynı şekilde, ziyaretçi kalıbı FP çözümüne (daha üst düzey bir işlev) göre garip / daha az doğaldır.
Giorgio

5

Çoğu işlevsel dil Nesneye Yönelik değildir. Bu, hiçbir nesneye sahip olmadıkları anlamına gelmez (kendileriyle ilişkili belirli işlevleri olan karmaşık türler anlamında). Haskell, java gibi Listeler, Haritalar, Diziler, her çeşit Ağaç ve daha birçok karmaşık türe sahiptir. Haskell Listesi veya Harita modülüne bakarsanız, çoğu eşdeğer OO dili kitaplığı modülündeki yöntemlere çok benzer bir dizi işlev görürsünüz. Kodu incelerseniz, bazı türler (veya kesin olarak kurucuları) ve yalnızca modüldeki diğer işlevler tarafından kullanılabilen işlevlerle benzer bir kapsülleme bile bulacaksınız.

Haskell'de bu tiplerle çalışma şekliniz genellikle OO yolundan pek farklı değildir. Haskell'de diyorum ki

  null xs
  length xs

ve Java’da

  xs.isEmpty
  xs.length

Domates, domates. Haskell işlevleri nesneye bağlı değildir, ancak türüyle yakından ilişkilidir. ¨Ah, ama , say diyorsun ki, ¨ Java’da , o nesnenin gerçek sınıfına hangi uzunluk yöntemine uygun olduğunu çağırıyor¨. Sürpriz - Haskell tip sınıflarıyla (ve diğer şeylerle) polimorfizm de yapıyor .

Haskell, ben varsa olduğunu - tamsayılar koleksiyonu - bu koleksiyon bir liste veya dizi veya dizi, bu kodu önemli değil ister

  fmap (* 2) is

tüm öğeleri ikiye katlayarak bir koleksiyon döndürür. Polimorfizm , spesifik tip için uygun harita fonksiyonunun çağırılacağı anlamına gelir .

Bu örnekler, gerçekte, gerçekten karmaşık türler değildir, ancak aynı şey daha zor problemler için de geçerlidir. İşlevsel dillerin karmaşık nesneleri modellemenize ve belirli işlevleri bunlarla ilişkilendirmenize izin vermediği fikri yanlıştır.

İşlevsel ve OO stili arasında önemli ve önemli farklılıklar vardır , ancak bu cevabın onlarla uğraşması gerektiğini düşünmüyorum. İşlevsel dillerin sorunların ve görevlerin sezgisel modellenmesini önleyip önlemediğini (veya engellediğini) sordunuz. Cevap hayır.


Nitekim Java / C # 'da type sınıflarını kullanabilirsiniz; yalnızca derleyicinin türüne göre doğru olanı çıkarmasını sağlamak yerine işlev sözlüğünü açıkça geçmeniz gerekir.
Doval

Kesinlikle. William Cook'un dediği gibi, kodlayıcı muhtemelen farkında olmasa da, çok sayıda OO kodu, daha yüksek seviyeli fonksiyonların işlevsel koddan daha sık kullanılmasını sağlar.
itsbruce

2
Yanlış bir ayrım yapıyorsunuz. Liste, bir yığın veya kuyruk veya tic-tac-toe simülatöründen daha fazla eylemsiz bir veri yapısı değildir. Bir liste her şeyi tutabilir (Haskell'de kısmen uygulanabilir fonksiyonlar olabilir) ve bu şeylerin nasıl etkileşime girebileceğini tanımlar. Kısmen uygulanan işlevlerle dolu bir listeyi başka bir değer listesine uygulayabilirsiniz ve sonuç, birinciden olası işlevlerin ikincisini ve ikinciden gelen girdiyi içeren yeni bir liste olur. Bu bir C yapısından çok daha fazlası.
itsbruce

3
Türler, zorunlu dillerde / OO'lardan daha çeşitli dillerde işlevsel diller için kullanılır (tür sistemleri, bir şey için daha güçlü ve tutarlı olma eğilimindedir). Türler ve işlevleri, kod yollarını şekillendirmek için kullanılır (bu nedenle, birkaç işlevsel dilde döngüler için anahtar sözcükler yoktur - gerekli değildir).
itsbruce

4
@Fuhrmanator "Bunun FP'de nasıl yapıldığını görmüyorum" Bu yüzden anlamadığınız bir şeyin mantıklı olmadığından şikayet ediyorsunuz; git öğren, iyice anlamış ve sonra mantıklı olacak. Belki mantıklı olduktan sonra bok olduğuna karar vereceksiniz ve yukarıdaki gibi insanlar bunu anlasa ve bu sonuca varmamış olsa da, bunu kanıtlamak için başkalarına ihtiyacınız yok. Silah dövüşüne bir bıçak getirmiş gibi görünüyorsunuz ve şimdi herkese silahların işe yaramaz olduğunu söylediniz çünkü keskin değiller.
Jimmy Hoffa

4

FP gerçekten temsili boşlukta bir azalma için çabalamaktadır:

İşlevsel dillerde çokça göreceğiniz bir şey, dili (aşağıdan yukarıya tasarım kullanarak) Gömülü Etki Alanına Özgü Dil (EDSL) haline getirme pratiğidir . Bu, işletme endişelerinizi programlama dilinde alan adınız için doğal bir şekilde ifade etmenin bir yolunu geliştirmenizi sağlar. Haskell ve Lisp bu konuda gurur duyuyorlar.

Bu yeteneği sağlayan şeyin bir kısmı (hepsi değilse de), temel dil (ler) in kendisinde daha fazla esneklik ve ifade gücüdür; birinci sınıf fonksiyonlar, yüksek dereceli fonksiyonlar, fonksiyon kompozisyonu ve bazı dillerde cebirsel veri türleri (AKA ayrımcı sendikalar) ve operatörleri * tanımlama yeteneği ile, şeyleri ifade etme konusunda OOP ile olduğundan daha fazla esneklik vardır. muhtemelen sorun alanınızdaki şeyleri ifade etmenin daha doğal yollarını bulacağınız anlamına gelir. (Birçok OOP dilinin, son zamanlarda bu özelliklerin çoğunu, onlarla başlamıyorsa, benimsediği bir şey söylemeliyiz.)

* Evet, birçok OOP dilinde standart operatörleri geçersiz kılabilirsiniz, ancak Haskell'de yenilerini tanımlayabilirsiniz!

İşlevsel dillerle (çoğunlukla F # ve Haskell, bazı Clojure ve biraz Lisp ve Erlang) çalışma deneyimime göre, sorunlu alanı OOP ile yaptığımdan daha kolay bir şekilde haritaya yerleştiriyorum - özellikle cebirsel veri türlerinde, derslerden daha esnek buluyorum. FP ile, özellikle Haskell ile başlarken beni bir döngü için atmış olan bir şey, emir veya OOP dillerinde alışkın olduğumdan biraz daha yüksek bir seviyede düşünmem / çalışmam gerektiğiydi; bununla da biraz uğraşıyor olabilirsiniz.


Ticari kaygılar (müşteriden gelen) üst düzey işlevlerde çok sık ifade edilmez. Ancak bir müşteri tek satırlık bir kullanıcı hikayesi yazabilir ve size iş kuralları sağlayabilir (veya bunları müşteriden çıkarabilirsiniz). Ben birinci sınıf fonksiyonları, vb harita eşleme sorunun soyutlama gelmesi sağlar (yukarıdan aşağıya?) Etki alanı modelleme (bu artefaktlar) ilgileniyorum. Bazı referanslar alıntı yapabilir misiniz? Bir alanın, soyutlamaların vs. somut bir örneğini kullanabilir misiniz?
Fuhrmanator

3
@Fuhrmanator Bir müşteri, OOP ve FP kullansanız da kullanmasanız da tek satırlık kullanıcı hikayeleri ve iş kuralları yazabilir . Müşterilerin üst düzey işlevleri miras, kompozisyon veya arayüzleri anlamalarını beklediğimden daha fazla anlamalarını beklemiyorum.
Andres

1
@Fuhrmanator Müşterinize Java jenerikleri veya soyut temel sınıflar ve arayüzler konusundaki endişelerini ne sıklıkta ifade ettiniz? Sevgili Tanrı'm. Paul, size görselleştirilemeyecek kadar zor olmayan teknikler kullanarak pratik ve güvenilir bir modelleme yöntemini açıklayan çok iyi bir cevap verdi. Ve yine de, belirli bir paradigma için belirli bir modelleme tekniği olarak tanımlanmasında ısrar ediyorsunuz, sanki tasarımı temsil etmenin bir şekilde en doğal yolu gibiydi ve başka bir şey kendi terimleriyle yeniden çizilebilir.
itsbruce

@Fuhrmanator Bu, aradığınız kadar yüksek düzeyde olmayabilir, ancak işlevsel teknikler kullanarak tasarım süreciyle ilgili bir fikir vermelidir: Türlerle Tasarım . Bazı mükemmel makaleler olduğu için genel olarak bu siteye göz atmanızı tavsiye ederim.
paul

@Fuhrmanator Ayrıca bu Düşünme Fonksiyonel serisi var
paul

3

Niklaus Wirth'in söylediği gibi, "Algoritmalar + Veri Yapıları = Programlar". Fonksiyonel programlama algoritmaları organize etme yolu ile ilgilidir ve veri yapılarını düzenleme yolları hakkında çok fazla şey anlatmaz. Gerçekten de mutable (Lisp) ve değişmez (Haskell, Erlang) değişkenleri olan FP dilleri vardır. FP'yi bir şeyle karşılaştırmak ve karşılaştırmak istiyorsanız, zorunlu (C, Java) ve bildirimsel (Prolog) programlamayı seçmelisiniz.

OOP ise veri yapıları oluşturmanın ve bunlara algoritmalar eklemenin bir yoludur. FP, OOP'lara benzer veri yapıları oluşturmanızı engellemez. Bana inanmıyorsanız Haskell tipi bildirimlere bir göz atın. Bununla birlikte, çoğu FP dili işlevlerin veri yapılarına ait olmadığını ve aynı ad alanında olması gerektiğini kabul eder. Bu, işlev kompozisyonu aracılığıyla yeni algoritmalar oluşturmayı basitleştirmek için yapılır. Gerçekten de, bir işlevin hangi girdiyi aldığını ve hangi çıktıyı ürettiğini biliyorsanız, neden hangi veri yapısına ait olduğu da önemli olsun? Örneğin, addişlevin neden bir Tamsayı türü örneğinde çağrılması ve yalnızca iki Tamsayı bağımsız değişkeninden geçmek yerine bir bağımsız değişken iletilmesi gerekir?

Bu nedenle, FP'nin neden çözümleri genel olarak anlaşılmasını zorlaştırması gerektiğini anlamıyorum ve yine de yaptığını sanmıyorum. Bununla birlikte, deneyimli bir zorunlu programcının zorunlu olanları kesinlikle zor programlardan daha zor anlayacağını ve tam tersini aklınızda bulundurun. Bu, Windows'a benzer - Windows ortamıyla rahat olmak için 10 yıl yatırım yapan kişiler bir aylık kullanımdan sonra Linux'u zor bulduğunda ve Linux'a alışkın olanlar Windows'da aynı üretkenliği elde edemediğinde Linux ikilemi. Dolayısıyla, bahsettiğiniz 'temsili boşluk' çok özneldir.


OO prensipleri olmayan kapsülleme ve veri gizleme nedeniyle, OO'nun veri yapıları + algoritmalar olduğu konusunda tamamen aynı fikirdeyim (bu sadece iç görünümdür). Herhangi bir iyi soyutlamanın güzelliği, sorunun bir kısmını çözmek için sağladığı çok fazla ayrıntıyı anlamaya gerek kalmadan hizmet vermesidir. FP'de fonksiyonları ve verileri ayırdığınızda kapsülleme hakkında konuştuğunuzu düşünüyorum, ancak emin olmak için çok yeşilim. Ayrıca, sorumu çözümden soruna geri dönme (temsili boşluğun anlamını açıklığa kavuşturmak için) anlamına gelecek şekilde düzenledim.
Fuhrmanator

if you know what input a function takes and what output it produces, why should it matter which data structure it belongs too?Bu, herhangi bir modüler sistem için önemli olan kohezyona çok benziyor. Bir işlevi nerede bulacağınızı bilmemenin, daha yüksek temsili boşluktan kaynaklanan bir çözümü anlamayı zorlaştıracağını iddia ediyorum. Birçok OO sistemi bu soruna sahiptir, ancak bunun nedeni kötü tasarımdan (düşük uyum) kaynaklanmaktadır. Yine, ad alanı sorunu FP'deki uzmanlığımın dışında, bu yüzden belki de göründüğü kadar kötü değil.
Fuhrmanator

1
@Fuhrmanator Ama yok yere bir fonksiyonu bulmak için biliyorum. Ve her bir veri tipi için tanımlanmış, aynı ada sahip birden fazla işlev olmayan tek bir işlev vardır (yine "İfade Sorunu" na bakınız). Örneğin, Haskell kütüphane işlevleri için (tekerleği yeniden keşfetmek veya adı geçen işlevlerin biraz daha az kullanışlı bir versiyonunu yapmak yerine kullanmanız önerilir), arama yapmanıza izin veren çok güçlü Hoogle gibi harika keşif araçlarınız vardır. imza ile (deneyin! :))
Andres F.

1
@Fuhrmanator, "Bu çok tutarlılık gibi geliyor" dan sonra, mantıksal olarak FP dillerinin daha yüksek uyum içeren programlar yazmanıza izin verdiği sonucuna varmanızı beklerdim ama beni şaşırtmıştınız. :-) Bence bir FP dili seçmeli, öğrenmeli ve kendi diline karar vermelisin. Ben olsaydım, Haskell ile başlamayı öneririm, çünkü oldukça saf ve bu yüzden zorunlu bir şekilde kod yazmanıza izin vermeyecek. Erlang ve bazı Lisp de iyi seçimlerdir, ancak diğer programlama stillerine karışırlar. Scala ve Clojure, IMO, başlangıçtan itibaren oldukça karmaşıktır.
mkalkov
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.