Haskell'in çoğu rutin programlama görevi için Monad'lar ve Uygulamalı İşlevler gibi gelişmiş kavramları ne kadar önemlidir?


16

Monad'ları ve Just a gibi şeyleri tanıttıkları noktaya kadar Haskell'i Öğrenin kitabını okudum. Bunlar benim için çok mantıklı ve öğrenmeye çalışmaktan vazgeçmek istiyorum.

Ama gerçekten denemek istiyorum.

En azından bir süreliğine gelişmiş kavramlardan kaçınıp kaçamayacağımı merak ediyorum ve sadece Haskell'in daha temel kısımlarıyla, yani işlevler, standart IO, dosya işleme, veritabanı arayüzü ve benzerleri.

Bu Haskell'in nasıl kullanılacağını öğrenmek için makul bir yaklaşım mıdır?


2
Ne kadar uzağa gideceğini bilmiyorum. Monadlar olmadan Haskell'de yararlı bir şey yapamazsınız, çünkü programlamada yararlı bir şey yapmak (birisinin gerçekten kullanmak isteyeceği ciddi bir program yazmak) G / Ç ve devlet gerektirir, her ikisi de sadece Haskell'de yönetilebilir Monadların kullanımıyla.
Mason Wheeler

1
@dan - Sonunda Haskell monad'larını iki belgeyi okuduğunu anladım - "Monadları icat etmiş olabilirsiniz" ve "Garip Kadroyla Mücadele". Okuma yazmadığım "Sana Haskell Öğren" den daha iyi olup olmadıklarını söyleyemem, ama onlar benim için çalıştı. IO monad ile do notasyonunu kullanmak için, monadların ne olduğunu çok az anlayarak başlayabilirsiniz - uzmanları güldürecek veya ağlatacak bazı şeyler yapacaksınız, ancak en azından yüzeysel olarak, kullanmaktan çok farklı değil geleneksel bir zorunlu dil. Ama olan bazı derin bir anlayış elde değerli.
Steve314

2
@dan, OOP'dan sıkılmam ve fonksiyonel dilleri takdir etmeye / merak etmeye başlamam yaklaşık on yıl sürdü. Haskell'e ciddi bir deneme yapmadan önce F # ve Clojure'u öğrenmeye devam ediyorum. Kişisel zorluklar güzel olsa da, bağırsak hissiniz ve en az direnç yolu hakkında söylenecek bir şey var. Çoğu kim olduğunuza bağlıdır. Güçlü bir mathy tipiyseniz, muhtemelen en başından itibaren Haskell / Schem'i istersiniz. Eğer bir 'olsun olsun' adam daha iseniz, o da tamam. Haskell'e 'yap ya da öl' tavrı ile yaklaşmayın. Başka şeyler öğrenmeye devam edin ve sıkıldığınızda geri gelin.
Meslek

@Job tavsiyeniz için teşekkürler. Clojure'u biraz denedim, ancak Lisp sözdizimi hem okuma hem de yazma için gerçekten işe yaramıyor. Haskell'in sözdizimini daha doğal buluyorum. Bu arada Ruby'yi projeler için kullandığım için mutluyum, ancak Haskell'de bazı pratik projeler yapmaya başlamayı umuyorum.
dan

@dan, Funny, Clojure'un sözdizimini oldukça arkadaşça buluyorum, ama muhtemelen daha önce Şema'ya maruz kaldım. Belki F # 'dan sonra Haskell'in işleri yapmasına alışacağım.
Meslek

Yanıtlar:


16

Önce soyut kavramları öğrenmek ve bunlara özgü örnekleri öğrenmek arasında ayrım yapalım .

Tamamen her yerde her yerde bulunmalarının basit nedenlerinden dolayı, tüm spesifik örnekleri görmezden gelmeyeceksiniz. Aslında, soyutlamalar büyük ölçüde mevcuttur, çünkü zaten yapacağınız şeyleri belirli örneklerle birleştirirler.

Diğer yandan soyutlamaların kendisi kesinlikle faydalıdır , ancak hemen gerekli değildir. Soyutlamaları tamamen görmezden gelebilir ve sadece çeşitli türleri doğrudan kullanabilirsiniz. Sonunda onları anlamak isteyeceksiniz, ancak daha sonra her zaman geri dönebilirsiniz. Aslında, bunu yaparsanız, ona geri döndüğünüzde alnınızı tokatlayacağınızı ve uygun genel amaçlı araçları kullanmak yerine neden bu kadar zaman harcadığınızı merak edeceğinizi neredeyse garanti edebilirim.

Örnek Maybe aolarak alalım. Bu sadece bir veri türüdür:

data Maybe a = Just a | Nothing

Her şey kendi kendini belgelemek dışında; isteğe bağlı bir değerdir. Ya "sadece" tipte bir aşeyiniz var ya da hiçbir şeyiniz yok. Var olmayan Maybe Stringbir Stringdeğere bakmayı temsil eden bir tür arama işleviniz olduğunu varsayalım . Öyleyse, hangisinin olduğunu görmek için değer üzerinde desen eşleşmesi yaparsınız:

case lookupFunc key of
    Just val -> ...
    Nothing  -> ...

Bu kadar!

Gerçekten, ihtiyacınız olan başka bir şey yok. Hayır Functorveya Monadbaşka bir şey yok. Bunlar Maybe adeğerleri kullanmanın yaygın yollarını ifade ederler ... ama sadece deyimdir, "tasarım kalıpları", ne derseniz deyin.

Gerçekten tamamen kaçınamayacağınız tek yer IO, ama yine de gizemli bir kara kutu, bu yüzden ne Monadveya ne anlama geldiğini anlamaya değmez .

Aslında, burada herkes için notlar bulunmaktadır gerçekten hakkında bilmeniz gereken IOşimdilik:

  • Bir şeyin bir türü varsa IO a, bu bir şey yapan ve bir değer veren bir prosedür olduğu anlamına gelir a.

  • doGösterimi kullanarak bir kod bloğunuz olduğunda , şöyle bir şey yazın:

    do -- ...
       inp <- getLine
       -- etc...
    

    ... işlemi prosedürün sağında yürütmek ve<- sonucu soldaki ada atamak anlamına gelir .

  • Halbuki böyle bir şeyiniz varsa:

    do -- ...
       let x = [foo, bar]
       -- etc...
    

    ... düz ifadenin değerini (yordam değil) =soldaki ada atamak anlamına gelir .

  • Oraya bir değer atamadan bir şey koyarsanız, şöyle:

    do putStrLn "blah blah, fishcakes"
    

    ... bir prosedürü yürütmek ve geri döndürdüğü her şeyi göz ardı etmek anlamına gelir. Bazı prosedürlerin türü vardır IO ()- ()tür, hiçbir şey söylemeyen bir tür yer tutucudur, bu nedenle prosedürün bir şey yaptığı ve bir değer döndürmediği anlamına gelir. voidDiğer dillerdeki gibi bir fonksiyon.

  • Aynı prosedürü birden fazla kez uygulamak farklı sonuçlar verebilir; bu bir fikir. Bu nedenle IO, değerini bir değerden "kaldırmanın" bir yolu yoktur , çünkü içindeki bir şey IObir değer değildir, bir değer elde etme prosedürüdür.

  • Bir dobloktaki son satır, atamasız düz bir prosedür olmalıdır, burada bu prosedürün dönüş değeri tüm blok için dönüş değeri olur. Dönüş değerinin önceden atanmış bir değeri kullanmasını istiyorsanız, returnişlev düz bir değer alır ve bu değeri döndüren bir işlem yapmama yordamı verir.

  • Bunun dışında özel bir şey yok IO; bu prosedürler aslında düz değerlerdir ve bunları etrafınızdan geçirebilir ve farklı şekillerde birleştirebilirsiniz. Sadece bir şey dodenilen bir blokta idam edildiğinde bir mainşey yaparlar.

Yani, bunun gibi sıkıcı, basmakalıp bir örnek programda:

hello = do putStrLn "What's your name?"
           name <- getLine
           let msg = "Hi, " ++ name ++ "!"
           putStrLn msg
           return name

... tıpkı zorunlu bir program gibi okuyabilirsiniz. Adlı bir prosedür tanımlıyoruz hello. Yürütüldüğünde, önce adınızı soran bir ileti yazdırmak için bir yordam yürütür; daha sonra bir girdi satırı okuyan bir prosedür yürütür ve sonucu şu şekilde atar name; daha sonra isme bir ifade atar msg; sonra mesajı yazdırır; daha sonra tüm bloğun sonucu olarak kullanıcının adını döndürür. A olduğundan name, bu , a döndüren yordam olduğu Stringanlamına gelir, bu nedenle türü vardır . Ve şimdi bu prosedürü tıpkı yürüttüğü gibi başka bir yerde yürütebilirsiniz .helloStringIO StringgetLine

Pfff, monadlar. Kimin onlara ihtiyacı var?


2
@dan: Çok hoş geldiniz! Yol boyunca belirli sorularınız varsa Yığın Taşması konusunda soru sormaktan çekinmeyin. [Haskell] etiketi genellikle oldukça aktiftir ve eğer insanlardan nereden geldiğinizi açıklarsanız, sadece şifreli cevapları atmaktan ziyade anlayış kazanmanıza yardımcı olurlar.
CA McCann

9

Haskell'in çoğu rutin programlama görevi için Monad'lar ve Uygulamalı İşlevler gibi gelişmiş kavramları ne kadar önemlidir?

Onlar esastır. Onlar olmadan, Haskell'i başka bir zorunlu dil olarak kullanmak çok kolay ve Simon Peyton Jones bir zamanlar dünyanın en iyi zorunlu programlama dili olan Haskell'i aramasına rağmen, hala en iyi kısmı kaçırıyorsunuz.

Monadlar, Monad Dönüşümleri, Monoidler, Functors, Uygulamalı Functors, Kontravarient Functors, Oklar, Kategoriler, vb. Bunlardan birine yaptığınız belirli bir şeyi sığdırdıktan sonra, soyut olarak yazılan büyük bir işlev zenginliğinden yararlanabilirsiniz. Bu tip sınıflar sadece sizi şaşırtmak için değil, hayatınızı kolaylaştırmak ve sizi daha üretken kılmak için oradalar. Bence, iyi Haskell kodunun kısaltılmasının en büyük nedeni bunlar.


1
+1: "Monads, Monad Transforms, Monoids, Functors, Uygulamalı Functors, Contravarient Functors, Arrows, Kategoriler, vb. Tasarım desenleri." !
Giorgio

7

Sadece bir şeylerin çalışmasını istiyorsanız kesinlikle gerekli mi? Hayır.

Güzel deyimsel Haskell programları yazmak istiyor musunuz? Kesinlikle.

Haskell'de programlama yaparken iki şeyi akılda tutmaya yardımcı olur:

  1. Tip sistemi size yardımcı olmak için orada. Programınızı oldukça polimorfik typeclass-heavy kodundan oluşturursanız, genellikle istediğiniz işlevin türünün (tek bir!) Doğru uygulamaya yönlendireceği harika duruma girebilirsiniz .

  2. Mevcut çeşitli kütüphaneler # 1 prensibi kullanılarak geliştirilmiştir.

Haskell'de bir program yazarken, türleri yazarak başlıyorum. Sonra baştan başladım ve daha genel tipler yazıyorum (ve mevcut tip sınıfların örnekleri olabilirler, hepsi daha iyi). Sonra bana istediğim türlerin değerlerini veren bazı fonksiyonlar yazıyorum. (Sonra onlarla oynuyorum ghcive belki de hızlı kontrol testleri yazıyorum.) Ve sonunda hepsini bir araya getiriyorum main.

Sadece bir şeylerin çalışmasını sağlayan çirkin Haskell yazmak mümkündür. Ancak o aşamaya ulaştığınızda öğrenecek daha çok şey var.

İyi şanslar!


1
Teşekkür ederim! Clojure ve Haskell arasında dolaşıyordum, ama şimdi senin gibi insanların ne kadar yardımcı oldukları için Haskell'e doğru eğildim.
dan

1
Haskell topluluğu çok güzel ve yararlı görünüyor. Ve birçok ilginç fikir nereden geliyor gibi görünüyor
Zachary K
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.