it-swarm.asia

Haskell veya diğer fonksiyonel programlama dillerindeki programları nasıl tasarlarsınız?

C # veya Ruby gibi nesne yönelimli programlama dillerinde biraz deneyimim var. Bir programın nesne yönelimli tarzda nasıl tasarlanacağını, sınıfların ve nesnelerin nasıl oluşturulacağını ve aralarındaki ilişkilerin nasıl tanımlanacağını biliyorum. Ayrıca bazı tasarım modellerini de biliyorum.

İnsanlar fonksiyonel programları nasıl yazıyor? Nasıl başlıyorlar? İşlevsel diller için tasarım kalıpları var mı? Aşırı programlama veya çevik geliştirme gibi metodolojiler fonksiyonel diller için uygulanabilir mi?

52
Luke

Cevabımı çoğunlukla Haskell düşünerek yazıyorum, ancak birçok kavram Erlang, LISP (ler) ve ML gibi diğer fonksiyonel diller için de aynı derecede geçerli. Hatta bazıları (bir dereceye kadar) Ruby, Python, Perl ve Javascript için de geçerlidir.

İnsanlar fonksiyonel programları nasıl yazıyor? Nasıl başlıyorlar?

Fonksiyonlar yazarak. İşlevsel programlama yaparken, main veya bir yardımcı işlev yazıyorsunuz. Bazen ana amacınız üzerinde çalışan çeşitli ilgili işlevlere sahip bir veri türü yazmak olabilir.

Fonksiyonel programlama hem yukarıdan aşağıya hem de aşağıdan yukarıya yaklaşımlar için çok uygundur. Haskell, programlarınızı üst düzey dilde yazmanızı ve daha sonra üst düzey tasarımınızın ayrıntılarını tanımlamanızı şiddetle tavsiye eder. Bkz. minimum, örneğin:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

Listedeki en küçük öğeyi bulma işlevi, her öğeyi "akümülatör" veya geçerli minimum değerle karşılaştırmak için min işlevini kullanarak, liste üzerinde bir geçiş olarak yazılır.

İşlevsel diller için tasarım kalıpları var mı?

"Tasarım örüntüleri" ile eşitlenebilecek iki şey vardır, imho, üst düzey fonksiyonlar ve monads. Birincisi hakkında konuşalım. Üst düzey işlevler, diğer işlevleri girdi olarak alan veya çıktı olarak işlev üreten işlevlerdir. Herhangi bir işlevsel dil genellikle map, filter ve fold 'ı yoğun olarak kullanır (katlama genellikle "azaltma" olarak da adlandırılır): işlevini bir listeye farklı şekillerde işler. Bunlar döngüler için kazan plakasını güzel bir şekilde değiştirir. Fonksiyonları parametre olarak geçirmek, programlamaya son derece güçlü bir nimettir; birçok "tasarım deseni", daha üst düzey işlevler kullanarak, kendiniz oluşturabileceğiniz ve kullanışlı işlevlerle dolu güçlü standart kitaplıktan yararlanarak daha basit bir şekilde gerçekleştirilebilir.

Monadlar "korkutucu" bir konudur. Ama gerçekten o kadar korkutucu değiller. Monad'ları düşünmenin en sevdiğim yolu, onları bir balonun içine bir fonksiyon sarmak ve bu fonksiyona süper güçler (sadece balonun içinde çalışan) vermek olarak düşünmektir. Ayrıntılara girebilirdim, ama dünyanın henüz başka bir monad benzetmesine ihtiyacı yok. Bu yüzden hızlı örneklere geçeceğim. Belirsiz bir "tasarım deseni" kullanmak istediğimi varsayalım. Aynı hesaplamayı farklı girdiler için aynı anda çalıştırmak istiyorum. Sadece bir girdi seçmek istemiyorum, hepsini seçmek istiyorum. Bu liste monad olurdu:

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

Şimdi, bunu yapmanın deyimsel yolu aslında map, ancak örnekleme adına, liste monadının bir değer üzerinde çalışıyormuş gibi görünen bir işlevi yazmamı nasıl sağladığını, ancak süper güçle donattığınızı görebiliyor musunuz? bir listedeki her öğe üzerinde çalışmak için? Diğer süper güçler arasında başarısızlık, durum, "dış dünya" ile etkileşim ve paralel yürütme bulunur. Bu süper güçler çok güçlüdür ve çoğu programlama dili, süper güçlere sahip işlevlerin her yerde rampa yapmasına izin verir. Çoğu insan Haskell'in bu süper güçlere hiç izin vermediğini söylüyor, ancak gerçekten, Haskell onları sadece monadlarda içeriyor, böylece etkileri sınırlı ve gözlenebilir.

tl; dr Grokking üst düzey fonksiyonları ve monadları, Haskell'in grokking tasarım modellerine eşdeğerdir. Bu Haskell kavramlarını öğrendikten sonra, "tasarım kalıpları" Haskell'in gücünü simüle etmek için çoğunlukla ucuz çözümlerdir.

Aşırı programlama veya çevik geliştirme gibi metodolojiler fonksiyonel diller için uygulanabilir mi?

Bu yönetim stratejilerini herhangi bir programlama paradigmasına bağlayan hiçbir şey görmüyorum. Phynfo'nun belirttiği gibi, fonksiyonel programlama pratik olarak kuvvetler fonksiyon ayrışması yapmak, büyük problemleri alt problemlere bölmek, böylece mini kilometre taşları bir parça kek olmalıdır. Yazdığınız işlevlerin özelliklerini test etmek veya hatta kanıtlamak için QuickCheck ve Zeno gibi araçlar vardır.

24
Dan Burton