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


52

C # veya ruby ​​gibi nesne yönelimli programlama dillerinde biraz deneyimim var. Bir programın nesne yönelimli bir tarzda nasıl tasarlanacağını, sınıf ve nesnelerin nasıl oluşturulacağını ve aralarındaki ilişkilerin nasıl tanımlanacağını biliyorum. Ayrıca bazı tasarım kalıplarını da biliyorum.

İnsanlar işlevsel programları nasıl yazarlar? Nasıl başlarlar? İşlevsel diller için tasarım desenleri var mı? İşlevsel diller için aşırı programlama veya çevik geliştirme gibi metodolojiler uygulanabilir mi?


Yanıtlar:


24

Cevabımı çoğunlukla Haskell'i aklımda tutuyorum, ancak birçok kavram Erlang, Lisp (ler) ve ML gibi diğer işlevsel dillere eşit derecede iyi uygulanıyor. Hatta bazıları Ruby, Python, Perl ve Javascript için de geçerlidir.

İnsanlar işlevsel programları nasıl yazarlar? Nasıl başlarlar?

İşlevleri yazarak. İşlevsel programlama yaparken, ya yazıyorsunuz mainya da bir yardımcı işlev yazıyorsunuz. Bazen asıl amacınız, üzerinde çalışan çeşitli ilgili fonksiyonlara sahip bir veri türü yazmak olabilir.

İşlevsel programlama hem yukarıdan aşağıya hem de aşağıdan yukarıya yaklaşımlara çok uygundur. Haskell, programlarınızı yüksek seviyede bir dilde yazmayı ve sonra da sadece üst düzey tasarımınızın ayrıntılarını tanımlamayı şiddetle teşvik eder. minimumÖrneğin, bakınız :

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

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

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

"Tasarım kalıpları" na eşdeğer olabilecek iki şey vardır: imho, üst düzey fonksiyonlar ve monadlar . Eski hakkında konuşalım. Üst düzey işlevler, giriş olarak diğer işlevleri alan veya çıktı olarak işlev üreten işlevlerdir. Herhangi işlevsel dil genellikle yoğun kullanımını gündeme getirmektedir map, filtervefold(katlama genellikle "azaltma" olarak da adlandırılır): bir listeye farklı şekillerde işlev uygulayan üç çok temel üst düzey işlev. Bunlar, güzel bir şekilde döngüler için kazan plakasını değiştirir. Fonksiyonları parametre olarak dolaşmak programlama için son derece güçlü bir nimettir; Çok sayıda "tasarım deseni", üst düzey işlevler kullanarak, kendi yönteminizi oluşturarak ve kullanışlı işlevlerle dolu güçlü standart kütüphaneden yararlanarak daha basit bir şekilde gerçekleştirilebilir.

Monad'lar "korkutucu" konudur. Ama onlar gerçekten o kadar korkutucu değiller. Monadları düşünmenin en sevdiğim yolu, onları bir balonun içinde bir işlevi saran ve bu işlevi süper güç veren (yalnızca balonun içinde çalışan) veren bir şey olarak düşünmektir. Ayrıntılı bilgi verebilirim, ancak dünyanın gerçekten başka bir monad analojisine ihtiyacı yok. Bu yüzden hızlı örneklere geçeceğim. Belirsiz olmayan bir "tasarım deseni" kullanmak istediğimi varsayalım. Aynı hesabı farklı girişler için aynı anda çalıştırmak istiyorum. Sadece bir giriş seçmek istemiyorum, hepsini seçmek istiyorum. Bu liste monad olur:

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

Şimdi, bunu yapmanın deyimsel yolu gerçektir map, ancak illüstrasyon uğruna, monad listesinin tek bir değerde işleyen gibi görünen bir işlevi yazmama nasıl izin verdiğini görebiliyor musunuz, ancak her bir öğenin üzerinde çalışmak için süper güçle donatıyorsunuz. bir liste? Diğer süper güçler arasında başarısızlık, devlet, "dış dünya" ile etkileşime girme ve paralel uygulama sayılabilir. Bu süper güçler çok güçlüdür ve programlama dillerinin çoğu, süper güçlere sahip fonksiyonların her tarafa yayılmasını sağlar. Çoğu kişi 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, grokking tasarım modellerine eşdeğer Haskell'dir. Bu Haskell kavramlarını öğrendikten sonra, "tasarım kalıplarının" Haskell'in gücünü taklit etmek için çoğunlukla ucuz geçici çözümler olduğunu düşünmeye başlarsınız.

İşlevsel diller için aşırı programlama veya çevik geliştirme gibi metodolojiler 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 sizi fonksiyon ayrıştırması yapmaya zorlar , büyük problemleri alt problemlere böler, bu yüzden mini-kilometre taşları bir parça kek olmalıdır. Yazdığınız fonksiyonlarla ilgili özellikleri test etmek ve hatta ispatlamak için QuickCheck ve Zeno gibi araçlar var.


“Ayrıntılı bilgi verebilirim, ancak dünyanın gerçekten başka bir monad analojisine ihtiyacı yok.” - Monadlar için daima daha fazla analojiye ihtiyacımız var ve seninkiler gördüğüm en iyilerden.
Adam Gent,

1
Harika cevap, ancak tasarım desenleriyle ilgili tartışmanızın biraz yanıltıcı olduğunu düşünüyorum. Haskell'de OO / GOF tarzı tasarım modellerine ihtiyacınız olmasa da - aslında onları denemek saçma olur - kalıplar kendilerini basitçe bir topluluğun tekrar tekrar ortaya çıkan sorunlara çözümler iletmesinin bir yoludur. Haskell topluluğu hala çok genç, bu yüzden konuşacak çok fazla kalıp yok, ama eğer bana Haskell kalıplarından örnekler sorarsanız, GADT'ler ya da Oklu FRP gibi şeyler söylerdim.
rtperson
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.