Ada apa dengan Haskell? [Tutup]

109

Saya mengenal beberapa programmer yang terus membicarakan Haskell ketika mereka berada di antara mereka sendiri, dan di sini, di SO semua orang tampaknya menyukai bahasa itu. Menjadi ahli di Haskell sepertinya merupakan ciri khas seorang programmer jenius.

Bisakah seseorang memberikan beberapa contoh Haskell yang menunjukkan mengapa itu sangat elegan / superior?

Frank
sumber

Jawaban:

134

Cara yang diberikan kepada saya, dan apa yang menurut saya benar setelah belajar di Haskell selama sebulan sekarang, adalah fakta bahwa pemrograman fungsional memelintir otak Anda dengan cara yang menarik: hal itu memaksa Anda untuk memikirkan masalah yang sudah dikenal dengan cara yang berbeda : alih-alih loop, pikirkan di peta dan lipatan dan filter, dll. Secara umum, jika Anda memiliki lebih dari satu perspektif tentang suatu masalah, itu membuat Anda lebih mampu untuk bernalar tentang masalah ini, dan beralih sudut pandang jika perlu.

Hal lain yang benar-benar rapi tentang Haskell adalah sistem tipenya. Ini diketik dengan ketat, tetapi mesin inferensi tipe membuatnya terasa seperti program Python yang secara ajaib memberi tahu Anda ketika Anda telah melakukan kesalahan terkait tipe yang bodoh. Pesan kesalahan Haskell dalam hal ini agak kurang, tetapi ketika Anda lebih mengenal bahasa yang akan Anda katakan kepada diri sendiri: inilah yang seharusnya mengetik!

Edward Z. Yang
sumber
47
Perlu dicatat bahwa pesan kesalahan Haskell tidak kurang, ghc ada. Standar Haskell tidak menentukan bagaimana pesan kesalahan dilakukan.
PyRulez
Untuk orang-orang kaya seperti saya, GHC adalah singkatan dari Glasgow Haskell Compiler. en.wikipedia.org/wiki/Glasgow_Haskell_Compiler
Lorem Ipsum
137

Ini adalah yang contoh yang meyakinkan saya untuk belajar Haskell (dan anak saya senang saya lakukan).

-- program to copy a file --
import System.Environment

main = do
         --read command-line arguments
         [file1, file2] <- getArgs

         --copy file contents
         str <- readFile file1
         writeFile file2 str

Oke, ini adalah program yang pendek dan dapat dibaca. Dalam hal ini lebih baik daripada program C. Tetapi apa bedanya dengan (katakanlah) program Python dengan struktur yang sangat mirip?

Jawabannya adalah evaluasi malas. Di sebagian besar bahasa (bahkan beberapa yang fungsional), program yang terstruktur seperti di atas akan mengakibatkan seluruh file dimuat ke memori, dan kemudian ditulis lagi dengan nama baru.

Haskell itu "malas". Itu tidak menghitung sesuatu sampai dibutuhkan, dan dengan ekstensi tidak menghitung hal-hal yang tidak pernah dibutuhkannya. Misalnya, jika Anda menghapus writeFilebaris, Haskell tidak akan repot-repot membaca apa pun dari file tersebut.

Karena itu, Haskell menyadari bahwa file writeFile bergantung pada readFile, dan karenanya mampu mengoptimalkan jalur data ini.

Meskipun hasilnya bergantung pada kompiler, yang biasanya akan terjadi saat Anda menjalankan program di atas adalah ini: program membaca blok (katakanlah 8KB) dari file pertama, lalu menulisnya ke file kedua, lalu membaca blok lain dari yang pertama file, dan menulisnya ke file kedua, dan seterusnya. (Coba laristrace di atasnya!)

... yang terlihat sangat mirip dengan implementasi C efisien dari salinan file yang akan dilakukan.

Jadi, Haskell memungkinkan Anda menulis program yang ringkas dan dapat dibaca - seringkali tanpa mengorbankan banyak kinerja.

Hal lain yang harus saya tambahkan adalah bahwa Haskell mempersulit penulisan program buggy. Sistem tipe yang luar biasa, kurangnya efek samping, dan tentu saja kekompakan kode Haskell mengurangi bug setidaknya untuk tiga alasan:

  1. Desain program yang lebih baik. Kompleksitas yang berkurang menyebabkan lebih sedikit kesalahan logika.

  2. Kode kompak. Lebih sedikit baris untuk bug berada.

  3. Mengompilasi kesalahan. Banyak bug yang bukan Haskell yang valid .

Haskell bukan untuk semua orang. Tetapi setiap orang harus mencobanya.

Artelius
sumber
Bagaimana tepatnya Anda akan mengubah konstanta 8KB (atau apa pun itu)? Karena saya berani bertaruh implementasi Haskell akan lebih lambat daripada versi C sebaliknya, terutama tanpa prefetching ...
user541686
1
@Mehrdad Anda dapat mengubah ukuran buffer dengan hSetBuffering handle (BlockBuffering (Just bufferSize)).
David
3
Sungguh menakjubkan bahwa jawaban ini memiliki 116 suara positif namun yang ada di dalamnya salah. Program ini akan membaca seluruh file, kecuali Anda menggunakan Bytestrings malas (yang dapat Anda lakukan dengan Data.Bytestring.Lazy.readFile), yang tidak ada hubungannya dengan Haskell sebagai bahasa malas (non-ketat). Monads adalah sequencing - berarti ini kira-kira "semua efek samping dilakukan ketika Anda mengambil hasilnya". Adapun sihir "Lazy Bytestring": ini berbahaya, dan Anda dapat melakukannya dengan sintaks yang serupa atau lebih sederhana di sebagian besar bahasa lain.
Jo Jadi
14
Standar lama yang membosankan readFilejuga melakukan IO malas dengan cara yang sama Data.ByteString.Lazy.readFile. Jadi jawabannya tidak salah, dan ini bukan sekedar optimasi compiler. Memang, ini adalah bagian dari spesifikasi untuk Haskell : " readFileFungsi membaca file dan mengembalikan konten file sebagai string. File dibaca dengan malas, sesuai permintaan, seperti halnya getContents."
Daniel Wagner
1
Saya pikir jawaban lain menunjukkan hal-hal yang lebih spesial tentang Haskell. Banyak bahasa / lingkungan memiliki aliran, Anda dapat melakukan sesuatu yang serupa di Node: const fs = require('fs'); const [file1, file2] = process.argv.slice(2); fs.createReadStream(file1).pipe(fs.createWriteStream(file2)). Bash memiliki sesuatu yang serupa juga:cat $1 > $2
Max Heiber
64

Anda semacam mengajukan pertanyaan yang salah.

Haskell bukanlah bahasa di mana Anda melihat beberapa contoh keren dan berkata "aha, saya mengerti sekarang, itulah yang membuatnya bagus!"

Ini lebih seperti, kita memiliki semua bahasa pemrograman lain, dan semuanya kurang lebih mirip, dan kemudian ada Haskell yang sama sekali berbeda dan aneh dengan cara yang benar-benar luar biasa setelah Anda terbiasa dengan keanehan. Namun masalahnya, perlu waktu cukup lama untuk menyesuaikan diri dengan keanehan tersebut. Hal-hal yang membedakan Haskell dari hampir semua bahasa lain yang bahkan semi-mainstream:

  • Evaluasi malas
  • Tidak ada efek samping (semuanya murni, IO / dll terjadi melalui monad)
  • Sistem tipe statis yang sangat ekspresif

serta beberapa aspek lain yang berbeda dari banyak bahasa utama (tetapi dimiliki oleh beberapa orang):

  • fungsional
  • spasi yang signifikan
  • ketik disimpulkan

Seperti yang telah dijawab oleh beberapa poster lain, kombinasi dari semua fitur ini berarti Anda berpikir tentang pemrograman dengan cara yang sama sekali berbeda. Jadi sulit untuk memberikan contoh (atau sekumpulan contoh) yang cukup mengkomunikasikan hal ini kepada Joe-mainstream-programmer. Itu adalah pengalaman. (Sebagai analogi, saya dapat menunjukkan foto perjalanan saya tahun 1970 ke China, tetapi setelah melihat foto-foto itu, Anda masih tidak akan tahu bagaimana rasanya tinggal di sana selama waktu itu. Demikian pula, saya dapat menunjukkan kepada Anda sebuah Haskell 'quicksort', tapi kamu masih belum tahu apa artinya menjadi Haskeller.)

Brian
sumber
17
Saya tidak setuju dengan kalimat pertama Anda. Saya sangat terkesan dengan beberapa contoh kode Haskell pada awalnya dan yang benar-benar meyakinkan saya bahwa itu layak dipelajari adalah artikel ini: cs.dartmouth.edu/~doug/powser.html Tapi tentu saja, ini menarik bagi seorang ahli matematika / fisikawan. Seorang programmer yang melihat ke dunia nyata akan menganggap contoh ini konyol.
Rafael S. Calsaverini
2
@Rafael: Itu menimbulkan pertanyaan "apa yang membuat programmer yang melihat ke dunia nyata terkesan oleh"?
JD
Pertanyaan bagus! Saya bukan programmer "dunia nyata" jadi saya tidak tahu apa yang mereka suka. hahaha ... Saya tahu seperti apa fisikawan dan matematikawan. : P
Rafael S. Calsaverini
27

Apa yang benar-benar membedakan Haskell adalah upaya yang dilakukan dalam desainnya untuk menerapkan pemrograman fungsional. Anda dapat memprogram dalam gaya fungsional dalam hampir semua bahasa, tetapi terlalu mudah untuk ditinggalkan begitu saja. Haskell tidak mengizinkan Anda untuk meninggalkan pemrograman fungsional, jadi Anda harus mengambil kesimpulan logisnya, yang merupakan program terakhir yang lebih mudah untuk dipikirkan, dan menghindari seluruh kelas dari jenis bug yang paling sulit.

Dalam hal menulis program untuk penggunaan dunia nyata, Anda mungkin menemukan Haskell kurang praktis, tetapi solusi akhir Anda akan lebih baik karena telah mengenal Haskell sejak awal. Saya jelas belum sampai di sana, tapi sejauh ini belajar Haskell jauh lebih mencerahkan daripada mengatakan, Lisp masih kuliah.

gtd
sumber
1
Nah, selalu ada kemungkinan untuk selalu dan hanya menggunakan monad ST dan / atau unsafePerformIOuntuk orang yang hanya ingin melihat dunia terbakar;)
sara
22

Bagian dari keributan adalah bahwa kemurnian dan pengetikan statis memungkinkan paralelisme dikombinasikan dengan optimisasi agresif. Bahasa paralel sedang panas sekarang dengan multicore menjadi sedikit mengganggu.

Haskell memberi Anda lebih banyak opsi untuk paralelisme daripada hampir semua bahasa tujuan umum, bersama dengan kompiler kode asli yang cepat. Sebenarnya tidak ada persaingan dengan jenis dukungan ini untuk gaya paralel:

Jadi jika Anda peduli tentang membuat multicore berfungsi, Haskell ingin mengatakan sesuatu. Tempat yang bagus untuk memulai adalah dengan tutorial Simon Peyton Jones tentang pemrograman paralel dan bersamaan di Haskell .

Don Stewart
sumber
"bersama dengan kompiler kode asli yang cepat"?
JD
Saya yakin don mengacu pada GHCI.
Gregory Higley
3
@Jon: shootout.alioth.debian.org/u32/… Haskell melakukannya dengan cukup baik dalam adu penalti, misalnya.
Peaker
4
@ Jon: Kode baku tembak sudah sangat tua, dan dari masa lalu di mana GHC kurang dari kompilator yang mengoptimalkan. Namun, ini membuktikan kode Haskell bisa turun ke level rendah untuk menghasilkan kinerja, jika diperlukan. Solusi yang lebih baru dalam baku tembak lebih idiomatik dan masih cepat.
Peaker
1
@GregoryHigley Ada perbedaan antara GHCI dan GHC.
Daftar Jeremy
18

Software Transactional Memory adalah cara yang cukup keren untuk menangani konkurensi. Ini jauh lebih fleksibel daripada penyampaian pesan, dan tidak rawan kebuntuan seperti mutex. Penerapan STM oleh GHC dianggap salah satu yang terbaik.

bmdhacks
sumber
18

Saya telah menghabiskan tahun lalu mempelajari Haskell dan menulis proyek yang cukup besar dan kompleks di dalamnya. (Proyek ini adalah sistem perdagangan opsi otomatis, dan segala sesuatu mulai dari algoritme perdagangan hingga penguraian dan penanganan umpan data pasar berkecepatan tinggi tingkat rendah dilakukan di Haskell.) Ini jauh lebih ringkas dan lebih mudah dipahami (bagi mereka yang memiliki latar belakang yang sesuai) daripada versi Java, dan juga sangat kuat.

Mungkin kemenangan terbesar bagi saya adalah kemampuan untuk memodulasi aliran kontrol melalui hal-hal seperti monoid, monad, dan sebagainya. Contoh yang sangat sederhana adalah Monoid Ordering; dalam ekspresi seperti

c1 `mappend` c2 `mappend` c3

di mana c1dan seterusnya kembali LT, EQatau GT, c1kembali EQmenyebabkan ekspresi berlanjut, mengevaluasi c2; jika c2kembali LTatau GTitulah nilai keseluruhan, dan c3tidak dievaluasi. Hal semacam ini menjadi jauh lebih canggih dan kompleks dalam hal-hal seperti generator dan parser pesan monadik di mana saya mungkin membawa berbagai jenis status, memiliki berbagai kondisi pembatalan, atau mungkin ingin dapat memutuskan untuk panggilan tertentu apakah benar-benar membatalkan "tidak ada pemrosesan lebih lanjut" atau artinya, "mengembalikan kesalahan di akhir, tetapi melanjutkan pemrosesan untuk mengumpulkan pesan kesalahan lebih lanjut."

Semua ini membutuhkan waktu dan upaya untuk mempelajarinya, dan karenanya akan sulit untuk membuat argumen yang meyakinkan untuk itu bagi mereka yang belum mengetahui teknik ini. Saya pikir tutorial All About Monads memberikan demonstrasi yang cukup mengesankan dari satu aspek ini, tetapi saya tidak berharap bahwa siapa pun yang tidak terbiasa dengan materi akan "mendapatkannya" pada bacaan pertama, atau bahkan ketiga, dengan cermat.

Bagaimanapun, ada banyak hal bagus lainnya di Haskell juga, tapi ini adalah hal utama yang tidak terlalu sering saya lihat, mungkin karena agak rumit.

Curt J. Sampson
sumber
2
Sangat menarik! Berapa total baris kode Haskell yang masuk ke sistem perdagangan otomatis Anda? Bagaimana Anda menangani toleransi kesalahan dan jenis hasil kinerja apa yang Anda dapatkan? Saya baru-baru ini berpikir bahwa Haskell berpotensi bagus untuk pemrograman latensi rendah ...
JD
12

Untuk contoh yang menarik, Anda dapat melihat: http://en.literateprograms.org/Quicksort_(Haskell)

Yang menarik adalah melihat implementasinya dalam berbagai bahasa.

Apa yang membuat Haskell begitu menarik, bersama dengan bahasa fungsional lainnya, adalah kenyataan bahwa Anda harus berpikir secara berbeda tentang bagaimana membuat program. Misalnya, Anda biasanya tidak akan menggunakan for atau while loop, tetapi akan menggunakan rekursi.

Seperti disebutkan di atas, Haskell dan bahasa fungsional lainnya unggul dengan pemrosesan paralel dan aplikasi penulisan untuk bekerja pada multi-core.

James Black
sumber
2
rekursi adalah bomnya. itu dan pencocokan pola.
Ellery Newcomer
1
Menyingkirkan loop for dan while adalah bagian tersulit bagi saya saat menulis dalam bahasa fungsional. :)
James Black
4
Belajar berpikir dalam rekursi alih-alih putaran adalah bagian tersulit bagi saya juga. Ketika akhirnya tenggelam, itu adalah salah satu pencerahan pemrograman terbesar yang pernah saya miliki.
Chris Connett
8
Kecuali programmer Haskell yang bekerja jarang menggunakan rekursi primitif; kebanyakan Anda menggunakan fungsi perpustakaan seperti map dan foldr.
Paul Johnson
18
Saya merasa lebih menarik bahwa algoritme quicksort asli Hoare diubah menjadi bentuk berbasis daftar yang tidak pada tempatnya ini tampaknya sehingga implementasi yang tidak efisien yang tidak berguna dapat ditulis "dengan elegan" di Haskell. Jika Anda mencoba menulis quicksort nyata (di tempat) di Haskell, Anda akan menganggapnya jelek sekali. Jika Anda mencoba menulis quicksort generik yang berkinerja kompetitif di Haskell, Anda akan menemukan bahwa hal itu sebenarnya tidak mungkin karena bug yang sudah lama ada di pengumpul sampah GHC. Memuji quicksort sebagai contoh yang baik untuk kepercayaan pengemis Haskell, IMHO.
JD
8

Saya tidak bisa memberi Anda contoh, saya seorang pria OCaml, tetapi ketika saya berada dalam situasi seperti Anda, rasa ingin tahu terus berlanjut dan saya harus mengunduh kompiler / juru bahasa dan mencobanya. Anda mungkin akan belajar lebih banyak dengan cara itu tentang kekuatan dan kelemahan bahasa fungsional tertentu.

maxaposteriori.dll
sumber
1
Jangan lupa untuk membaca kode sumber kompiler. Itu juga akan memberi Anda banyak informasi berharga.
JD
7

Satu hal yang saya anggap sangat keren ketika berhadapan dengan algoritma atau masalah matematika adalah evaluasi malas Haskell yang melekat pada komputasi, yang hanya mungkin karena sifat fungsionalnya yang ketat.

Misalnya, jika Anda ingin menghitung semua bilangan prima, Anda dapat menggunakan

primes = sieve [2..]
    where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]

dan hasilnya sebenarnya adalah daftar yang tak terbatas. Tetapi Haskell akan mengevaluasinya dari kiri dari kanan, jadi selama Anda tidak mencoba melakukan sesuatu yang memerlukan seluruh daftar, Anda masih dapat menggunakannya tanpa program macet di tak terhingga, seperti:

foo = sum $ takeWhile (<100) primes

yang menjumlahkan semua bilangan prima kurang dari 100. Ini bagus karena beberapa alasan. Pertama-tama, saya hanya perlu menulis satu fungsi prima yang menghasilkan semua bilangan prima dan kemudian saya cukup siap untuk bekerja dengan bilangan prima. Dalam bahasa pemrograman berorientasi objek, saya memerlukan beberapa cara untuk memberi tahu fungsi berapa banyak bilangan prima yang harus dihitung sebelum kembali, atau meniru perilaku daftar tak terbatas dengan objek. Hal lain adalah bahwa secara umum, Anda akhirnya menulis kode yang mengekspresikan apa yang ingin Anda hitung dan bukan dalam urutan mana untuk mengevaluasi sesuatu - sebaliknya compiler yang melakukannya untuk Anda.

Ini tidak hanya berguna untuk daftar yang tidak terbatas, pada kenyataannya ini digunakan tanpa Anda menyadarinya setiap saat ketika tidak perlu mengevaluasi lebih dari yang diperlukan.

waxwing
sumber
2
Ini tidak sepenuhnya benar; dengan perilaku pengembalian hasil C # (bahasa berorientasi objek), Anda juga dapat mendeklarasikan daftar tak terbatas yang dievaluasi sesuai permintaan.
Jeff Yates
2
Poin yang bagus. Anda benar dan saya harus menghindari pernyataan apa yang bisa dan tidak bisa dilakukan dalam bahasa lain secara kategoris. Saya pikir contoh saya cacat, tetapi saya masih berpikir Anda mendapatkan sesuatu dari cara evaluasi malas Haskell: itu benar-benar ada secara default dan tanpa usaha dari programmer. Dan ini, saya yakin, karena sifat fungsionalnya dan tidak adanya efek samping.
waxwing
8
Anda mungkin tertarik untuk membaca mengapa "saringan" bukan Saringan Eratosthenes: lambda-the-ultimate.org/node/3127
Chris Conway
@Chris: Terima kasih, itu sebenarnya artikel yang cukup menarik! Fungsi bilangan prima di atas bukan yang saya gunakan untuk perhitungan saya sendiri karena sangat lambat. Namun demikian, artikel tersebut memberikan poin bagus bahwa memeriksa semua angka untuk mod benar-benar merupakan algoritme yang berbeda.
waxwing
6

Saya setuju dengan orang lain bahwa melihat beberapa contoh kecil bukanlah cara terbaik untuk memamerkan Haskell. Tapi aku akan tetap memberikannya. Berikut adalah solusi secepat kilat untuk masalah Proyek Euler 18 dan 67 , yang meminta Anda untuk menemukan jalur jumlah maksimum dari alas ke puncak segitiga:

bottomUp :: (Ord a, Num a) => [[a]] -> a
bottomUp = head . bu
  where bu [bottom]     = bottom
        bu (row : base) = merge row $ bu base
        merge [] [_] = []
        merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)

Berikut adalah implementasi algoritme BubbleSearch yang lengkap dan dapat digunakan kembali oleh Lesh dan Mitzenmacher. Saya menggunakannya untuk mengemas file media besar untuk penyimpanan arsip di DVD tanpa limbah:

data BubbleResult i o = BubbleResult { bestResult :: o
                                     , result :: o
                                     , leftoverRandoms :: [Double]
                                     }
bubbleSearch :: (Ord result) =>
                ([a] -> result) ->       -- greedy search algorithm
                Double ->                -- probability
                [a] ->                   -- list of items to be searched
                [Double] ->              -- list of random numbers
                [BubbleResult a result]  -- monotone list of results
bubbleSearch search p startOrder rs = bubble startOrder rs
    where bubble order rs = BubbleResult answer answer rs : walk tries
            where answer = search order
                  tries  = perturbations p order rs
                  walk ((order, rs) : rest) =
                      if result > answer then bubble order rs
                      else BubbleResult answer result rs : walk rest
                    where result = search order

perturbations :: Double -> [a] -> [Double] -> [([a], [Double])]
perturbations p xs rs = xr' : perturbations p xs (snd xr')
    where xr' = perturb xs rs
          perturb :: [a] -> [Double] -> ([a], [Double])
          perturb xs rs = shift_all p [] xs rs

shift_all p new' [] rs = (reverse new', rs)
shift_all p new' old rs = shift_one new' old rs (shift_all p)
  where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b
        shift_one new' xs rs k = shift new' [] xs rs
          where shift new' prev' [x] rs = k (x:new') (reverse prev') rs
                shift new' prev' (x:xs) (r:rs) 
                    | r <= p    = k (x:new') (prev' `revApp` xs) rs
                    | otherwise = shift new' (x:prev') xs rs
                revApp xs ys = foldl (flip (:)) ys xs

Saya yakin kode ini terlihat seperti omong kosong acak. Tetapi jika Anda membaca entri blog Mitzenmacher dan memahami algoritme, Anda akan kagum bahwa algoritme dapat dikemas ke dalam kode tanpa mengatakan apa pun tentang apa yang Anda cari.

Setelah memberi Anda beberapa contoh seperti yang Anda minta, saya akan mengatakan bahwa cara terbaik untuk mulai menghargai Haskell adalah dengan membaca makalah yang memberi saya ide-ide yang saya perlukan untuk menulis pengemas DVD: Why Functional Programming Matters oleh John Hughes. Makalah ini sebenarnya sudah ada sebelum Haskell, tetapi dengan cemerlang menjelaskan beberapa ide yang membuat orang menyukai Haskell.

Norman Ramsey
sumber
5

Bagi saya, daya tarik Haskell adalah janji compiler yang dijamin benar. Bahkan jika itu untuk bagian murni dari kode.

Saya telah menulis banyak kode simulasi ilmiah, dan bertanya-tanya begitu banyak kali jika ada bug dalam kode saya sebelumnya, yang bisa membatalkan banyak pekerjaan saat ini.

rpg
sumber
6
Bagaimana cara menjamin kebenaran?
Jonathan Fischoff
Bagian kode yang murni jauh lebih aman daripada bagian yang tidak murni. Tingkat kepercayaan / usaha yang diinvestasikan jauh lebih tinggi.
rpg
1
Apa yang memberi Anda kesan itu?
JD
5

Saya menemukan bahwa untuk tugas-tugas tertentu saya sangat produktif dengan Haskell.

Alasannya karena sintaks yang ringkas dan kemudahan pengujian.

Seperti inilah sintaks deklarasi fungsi:

foo a = a + 5

Itu adalah cara paling sederhana yang bisa saya pikirkan untuk mendefinisikan suatu fungsi.

Jika saya menulis kebalikannya

inverseFoo a = a - 5

Saya dapat memeriksa bahwa ini adalah kebalikan dari masukan acak dengan menulis

prop_IsInverse :: Ganda -> Bool
prop_IsInverse a = a == (inverseFoo $ foo a)

Dan menelepon dari baris perintah

jonny @ ubuntu: runhaskell quickCheck + nama fooFileName.hs

Yang akan memeriksa bahwa semua properti di file saya dipegang, dengan menguji input secara acak ratusan kali.

Saya tidak berpikir Haskell adalah bahasa yang sempurna untuk semuanya, tetapi ketika menulis fungsi dan pengujian kecil, saya belum melihat yang lebih baik. Jika pemrograman Anda memiliki komponen matematika, ini sangat penting.

Jonathan Fischoff
sumber
Masalah apa yang Anda pecahkan dan bahasa lain apa yang sudah Anda coba?
JD
1
Grafik 3d waktu nyata untuk ponsel dan iPad.
Jonathan Fischoff
3

Jika Anda dapat memahami sistem tipe di Haskell, saya pikir itu sendiri sudah merupakan pencapaian yang cukup.

Dr Watson
sumber
1
Apa yang bisa didapat? Jika Anda harus, pikirkan "data" == "class" dan "typeclass" = "interface" / "role" / "trait". Tidak bisa lebih sederhana. (Bahkan tidak ada "null" untuk mengacaukan Anda. Null adalah konsep yang dapat Anda bangun sendiri ke dalam tipe Anda.)
jrockway
8
Ada banyak hal yang bisa didapat, jrockway. Meskipun Anda dan saya menganggapnya relatif mudah, banyak orang - bahkan banyak pengembang - menemukan jenis abstraksi tertentu sangat sulit untuk dipahami. Saya tahu banyak pengembang yang masih belum begitu memahami gagasan tentang petunjuk dan referensi dalam bahasa yang lebih umum, meskipun mereka menggunakannya setiap hari.
Gregory Higley
2

itu tidak memiliki konstruksi loop. tidak banyak bahasa yang memiliki ciri ini.

Badri
sumber
17
ghci>: m + Control.Monad ghci> forM_ [1..3] cetak 1 2 3
sastanin
1

Saya setuju dengan mereka yang mengatakan bahwa pemrograman fungsional memelintir otak Anda untuk melihat pemrograman dari sudut yang berbeda. Saya hanya menggunakannya sebagai penghobi, tapi saya pikir itu secara mendasar mengubah cara saya mendekati suatu masalah. Saya rasa saya tidak akan seefektif LINQ tanpa terpapar Haskell (dan menggunakan generator dan pemahaman daftar dengan Python).

Yakub
sumber
-1

Untuk menyuarakan pandangan yang berlawanan: Steve Yegge menulis bahwa bahasa Hindely-Milner tidak memiliki fleksibilitas yang diperlukan untuk menulis sistem yang baik :

HM sangat cantik, dalam arti matematika formal yang sama sekali tidak berguna. Ia menangani beberapa konstruksi komputasi dengan sangat baik; pengiriman pencocokan pola yang ditemukan di Haskell, SML dan OCaml sangat berguna. Tidak mengherankan, ini menangani beberapa konstruksi umum dan sangat diinginkan lainnya dengan canggung, tetapi mereka menjelaskan skenario itu dengan mengatakan bahwa Anda salah, Anda sebenarnya tidak menginginkannya. Anda tahu, hal-hal seperti, oh, mengatur variabel.

Haskell memang layak dipelajari, tetapi ia memiliki kelemahannya sendiri.

RossFabricant
sumber
5
Meskipun memang benar bahwa sistem tipe yang kuat umumnya mengharuskan Anda untuk mematuhinya (itulah yang membuat kekuatannya berguna), itu juga merupakan kasus bahwa banyak (sebagian besar?) Sistem tipe berbasis HM yang ada, pada kenyataannya, memiliki beberapa jenis ' escape hatch 'seperti yang dijelaskan di link (ambil Obj.magic di O'Caml sebagai contoh, meskipun saya tidak pernah menggunakannya kecuali sebagai hack); dalam prakteknya, bagaimanapun, untuk banyak jenis program seseorang tidak pernah membutuhkan alat seperti itu.
Zach Snow
3
Pertanyaan tentang apakah variabel pengaturan "diinginkan" tergantung pada seberapa besar rasa sakit menggunakan konstruksi alternatif vs berapa banyak rasa sakit yang disebabkan oleh penggunaan variabel. Itu tidak berarti mengabaikan keseluruhan argumen, melainkan untuk menunjukkan bahwa mengambil pernyataan "variabel adalah konstruksi yang sangat diinginkan" sebagai aksioma bukanlah dasar dari argumen yang meyakinkan. Kebetulan itulah cara kebanyakan orang belajar membuat program.
gtd
5
-1: Pernyataan Steve sebagian sudah kadaluwarsa tetapi sebagian besar secara faktual salah. Pembatasan nilai santai OCaml dan sistem tipe .NET adalah beberapa contoh kontra yang jelas untuk pernyataannya.
JD
4
Steve Yegge memiliki lebah yang tidak masuk akal di kap mesinnya tentang pengetikan statis, dan tidak hanya sebagian besar dari apa yang dia katakan tentang hal itu salah, dia juga terus mengemukakannya di setiap kesempatan yang tersedia (dan bahkan beberapa yang tidak tersedia). Anda sebaiknya hanya mempercayai pengalaman Anda sendiri dalam hal ini.
ShreevatsaR
3
Meskipun saya tidak setuju dengan Yegge tentang pengetikan statis vs. dinamis, Haskell memang memiliki tipe Data.Dynamic. Jika Anda ingin mengetik dinamis, Anda dapat memilikinya!
jrockway