Tại sao Haskell (GHC) rất nhanh?


246

Haskell (với GHCtrình biên dịch) nhanh hơn rất nhiều so với bạn mong đợi . Được sử dụng một cách chính xác, nó có thể có được các ngôn ngữ cấp thấp. (Một điều yêu thích của Haskeller phải làm là thử và nhận trong vòng 5% C (hoặc thậm chí đánh bại nó, nhưng điều đó có nghĩa là bạn đang sử dụng chương trình C không hiệu quả, vì GHC biên dịch Haskell thành C). Câu hỏi của tôi là, tại sao?

Haskell là khai báo và dựa trên tính toán lambda. Kiến trúc máy rõ ràng là bắt buộc, dựa trên các máy turing, đại khái. Thật vậy, Haskell thậm chí không có một thứ tự đánh giá cụ thể. Ngoài ra, thay vì xử lý các loại dữ liệu máy, bạn luôn tạo các loại dữ liệu đại số.

Lạ nhất trong tất cả là chức năng bậc cao. Bạn sẽ nghĩ rằng việc tạo các chức năng một cách nhanh chóng và ném chúng xung quanh sẽ khiến chương trình chậm hơn. Nhưng sử dụng các hàm bậc cao hơn thực sự làm cho Haskell nhanh hơn. Thật vậy, có vẻ như, để tối ưu hóa mã Haskell, bạn cần làm cho nó thanh lịch và trừu tượng hơn thay vì giống máy hơn. Không có tính năng nâng cao nào của Haskell dường như thậm chí ảnh hưởng đến hiệu suất của nó, nếu họ không cải thiện nó.

Xin lỗi nếu điều này nghe có vẻ khó hiểu, nhưng đây là câu hỏi của tôi: Tại sao Haskell (được biên dịch với GHC) lại nhanh như vậy, xem xét tính chất trừu tượng và sự khác biệt của nó so với máy vật lý?

Lưu ý: Lý do tôi nói C và các ngôn ngữ mệnh lệnh khác có phần giống với Turing Machines (nhưng không đến mức Haskell giống với Lambda Tính) là trong một ngôn ngữ bắt buộc, bạn có số lượng trạng thái hữu hạn (còn gọi là số dòng) , cùng với một Băng (ram), sao cho trạng thái và băng hiện tại xác định những việc cần làm đối với băng. Xem mục Wikipedia, tương đương máy Turing , để biết quá trình chuyển đổi từ Turing Machines sang máy tính.


27
"vì GHC biên dịch Haskell thành C" - không. GHC có nhiều phụ trợ. Cái cũ nhất (nhưng không phải mặc định) là một trình tạo C. Nó tạo mã Cmm cho IR, nhưng đó không phải là "biên dịch thành C" mà bạn thường mong đợi. ( lượt tải
xuống.haskell.org/~ghc/latest/docs/html/usftimefide/ide

19
Tôi đặc biệt khuyên bạn nên đọc Thực hiện ngôn ngữ lập trình chức năng của Simon Payton Jones (người triển khai chính của GHC) nó sẽ trả lời rất nhiều câu hỏi của bạn.
Joe Hillenbrand

94
Tại sao? 25 năm làm việc chăm chỉ.
tăng

31
"Mặc dù có thể có một câu trả lời thực tế cho nó, nó sẽ không làm gì ngoài việc lấy ý kiến." - Đây là lý do tồi tệ nhất có thể để đóng một câu hỏi. Bởi vì nó có thể có một câu trả lời tốt, nhưng nó cũng có khả năng sẽ thu hút những câu trả lời chất lượng thấp. Kinh quá! Tôi rất tình cờ có một câu trả lời hay, lịch sử, thực tế xếp hàng về nghiên cứu học thuật và khi những phát triển nhất định xảy ra. Nhưng tôi không thể đăng nó vì mọi người lo lắng câu hỏi này cũng có thể thu hút các câu trả lời chất lượng thấp. Một lần nữa, yuck.
sclv

7
@cimmanon Tôi sẽ cần một tháng hoặc một vài bài đăng trên blog để tìm hiểu những điều cơ bản về các chi tiết về cách trình biên dịch chức năng hoạt động. Tôi chỉ cần một câu trả lời SO để phác thảo trong phác thảo rộng về cách một máy đồ thị có thể được triển khai sạch trên phần cứng chứng khoán và chỉ đến các nguồn có liên quan để đọc thêm ...
sclv

Câu trả lời:


264

Tôi đồng ý với Dietrich Epp: đó là sự kết hợp của một số thứ giúp GHC nhanh chóng.

Đầu tiên và quan trọng nhất, Haskell rất cao cấp. Điều này cho phép trình biên dịch thực hiện tối ưu hóa tích cực mà không phá vỡ mã của bạn.

Hãy nghĩ về SQL. Bây giờ, khi tôi viết một SELECTtuyên bố, nó có thể trông giống như một vòng lặp bắt buộc, nhưng nó không phải là . Có vẻ như nó lặp lại trên tất cả các hàng trong bảng đó khi cố gắng tìm một hàng khớp với các điều kiện đã chỉ định, nhưng thực ra "trình biên dịch" (công cụ DB) có thể thực hiện tra cứu chỉ mục - có đặc điểm hiệu suất hoàn toàn khác. Nhưng vì SQL rất cao cấp, "trình biên dịch" có thể thay thế các thuật toán hoàn toàn khác nhau, áp dụng nhiều bộ xử lý hoặc kênh I / O hoặc toàn bộ máy chủ một cách trong suốt, v.v.

Tôi nghĩ về Haskell là như nhau. Bạn có thể nghĩ rằng bạn vừa yêu cầu Haskell ánh xạ danh sách đầu vào vào danh sách thứ hai, lọc danh sách thứ hai vào danh sách thứ ba và sau đó đếm xem có bao nhiêu mục kết quả. Nhưng bạn đã không thấy GHC áp dụng các quy tắc viết lại hợp nhất luồng phía sau hậu trường, biến toàn bộ thành một vòng mã máy chặt chẽ duy nhất thực hiện toàn bộ công việc trong một lần truyền dữ liệu mà không cần phân bổ - loại điều sẽ xảy ra tẻ nhạt, dễ bị lỗi và không thể bảo trì để viết bằng tay. Điều đó chỉ thực sự khả thi vì thiếu các chi tiết cấp thấp trong mã.

Một cách khác để xem xét nó có thể là lỗi tại sao Haskell không nên nhanh? Nó làm gì mà làm cho nó chậm lại?

Đây không phải là ngôn ngữ được dịch như Perl hay JavaScript. Nó thậm chí không phải là một hệ thống máy ảo như Java hay C #. Nó biên dịch tất cả các mã nguồn gốc, do đó không có chi phí nào ở đó.

Không giống như các ngôn ngữ OO [Java, C #, JavaScript,], Haskell có kiểu xóa hoàn toàn [như C, C ++, Pascal,]. Tất cả các loại kiểm tra chỉ xảy ra tại thời gian biên dịch. Vì vậy, không có kiểm tra loại thời gian chạy để làm chậm bạn. (Không có kiểm tra con trỏ null, đối với vấn đề đó. Trong giả sử, Java, JVM phải kiểm tra các con trỏ null và ném ngoại lệ nếu bạn trì hoãn một.

Bạn nói rằng nghe có vẻ chậm khi "tạo các chức năng một cách nhanh chóng", nhưng nếu bạn xem xét rất kỹ, bạn thực sự không làm điều đó. Nó có thể trông giống như bạn, nhưng bạn thì không. Nếu bạn nói (+5), tốt, đó là mã hóa cứng vào mã nguồn của bạn. Nó không thể thay đổi trong thời gian chạy. Vì vậy, nó không thực sự là một chức năng động. Ngay cả các hàm bị cong thực sự chỉ là lưu các tham số vào một khối dữ liệu. Tất cả các mã thực thi thực sự tồn tại tại thời gian biên dịch; không có giải thích thời gian chạy. (Không giống như một số ngôn ngữ khác có "chức năng eval".)

Hãy nghĩ về Pascal. Nó đã cũ và không ai thực sự sử dụng nó nữa, nhưng không ai phàn nàn rằng Pascal chậm . Có rất nhiều điều không thích về nó, nhưng sự chậm chạp không thực sự là một trong số đó. Haskell không thực sự làm được nhiều điều khác với Pascal, ngoài việc có bộ sưu tập rác thay vì quản lý bộ nhớ thủ công. Và dữ liệu bất biến cho phép một số tối ưu hóa cho công cụ GC [việc đánh giá lười biếng sau đó làm phức tạp phần nào].

Tôi nghĩ vấn đề là Haskell có vẻ tiên tiến, tinh vi và cao cấp, và mọi người đều nghĩ "oh wow, điều này thực sự mạnh mẽ, nó phải chậm một cách đáng kinh ngạc! " Nhưng không phải vậy. Hoặc ít nhất, nó không theo cách bạn mong đợi. Vâng, nó có một hệ thống loại tuyệt vời. Nhưng bạn biết gì không? Đó là tất cả xảy ra tại thời gian biên dịch. Đến giờ chạy, nó biến mất. Có, nó cho phép bạn xây dựng các ADT phức tạp với một dòng mã. Nhưng bạn biết gì không? Một ADT chỉ là một C bình thường đơn giản unioncủa structs. Chỉ có bấy nhiêu thôi.

Kẻ giết người thực sự là đánh giá lười biếng. Khi bạn nhận được sự nghiêm ngặt / lười biếng của mã của mình, bạn có thể viết mã nhanh một cách ngu ngốc mà vẫn thanh lịch và đẹp. Nhưng nếu bạn hiểu sai thứ này, chương trình của bạn sẽ chậm hơn hàng ngàn lần và thực sự không rõ ràng tại sao điều này lại xảy ra.

Ví dụ, tôi đã viết một chương trình nhỏ tầm thường để đếm số lần mỗi byte xuất hiện trong một tệp. Đối với tệp đầu vào 25KB, chương trình mất 20 phút để chạy và nuốt 6 GB RAM! Đó là vô lý!! Nhưng sau đó tôi nhận ra vấn đề là gì, thêm một kiểu tiếng nổ duy nhất và thời gian chạy giảm xuống 0,02 giây .

Đây là nơi Haskell bất ngờ đi chậm. Và nó chắc chắn phải mất một thời gian để làm quen với nó. Nhưng theo thời gian, việc viết mã thực sự nhanh hơn sẽ dễ dàng hơn.

Điều gì làm cho Haskell nhanh như vậy? Độ tinh khiết. Các loại tĩnh. Lười biếng. Nhưng trên hết, đủ trình độ cao để trình biên dịch có thể thay đổi hoàn toàn việc triển khai mà không phá vỡ kỳ vọng của mã của bạn.

Nhưng tôi đoán đó chỉ là ý kiến ​​của tôi ...


13
@cimmanon Tôi không nghĩ nó hoàn toàn dựa trên quan điểm. Đó là một câu hỏi thú vị mà những người khác có thể muốn có câu trả lời. Nhưng tôi đoán chúng ta sẽ thấy những cử tri khác nghĩ gì.
Toán học,

8
@cimmanon - tìm kiếm đó chỉ cung cấp một chủ đề rưỡi và tất cả đều phải thực hiện với kiểm toán đánh giá. và câu trả lời được nêu lên cho chủ đề "vui lòng dừng kiểm duyệt những thứ bạn không hiểu." Tôi sẽ đề nghị rằng nếu ai đó nghĩ rằng câu trả lời cho điều này nhất thiết phải quá rộng thì họ sẽ ngạc nhiên và thích câu trả lời, vì câu trả lời không quá rộng.
sclv

34
"Trong, giả sử, Java, JVM phải kiểm tra các con trỏ null và đưa ra một ngoại lệ nếu bạn trì hoãn một con trỏ." Kiểm tra null ẩn của Java là (hầu hết) không tốn kém. Việc triển khai Java có thể và tận dụng bộ nhớ ảo để ánh xạ địa chỉ null vào một trang bị thiếu, do đó, việc hủy bỏ một con trỏ null sẽ gây ra lỗi trang ở cấp CPU, mà Java bắt và ném như một ngoại lệ cấp cao. Vì vậy, hầu hết các kiểm tra null được thực hiện miễn phí bởi đơn vị ánh xạ bộ nhớ trong CPU.
Boann

4
@cimmanon: Có lẽ đó là bởi vì người dùng Haskell dường như là cộng đồng duy nhất thực sự là một nhóm người cởi mở thân thiện mà bạn coi là một trò đùa đùa, thay vì một cộng đồng cai trị chó ăn thịt chó xé toạc cho nhau một cơ hội mới trong mọi cơ hội họ nhận được, đó dường như là những gì bạn coi là bình thường.
Evi1M4chine

14
@MathologistsOrchid: bạn có bản sao chương trình gốc mất 20 phút để chạy không? Tôi nghĩ sẽ rất hữu ích khi nghiên cứu tại sao nó lại chậm như vậy.
George

79

Trong một thời gian dài, người ta đã nghĩ rằng các ngôn ngữ chức năng không thể nhanh - và đặc biệt là các ngôn ngữ chức năng lười biếng. Nhưng điều này là do các triển khai ban đầu của họ, về bản chất, đã được giải thích và không được biên soạn thực sự.

Một làn sóng thiết kế thứ hai xuất hiện dựa trên việc giảm đồ thị, và mở ra khả năng biên dịch hiệu quả hơn nhiều. Simon Peyton Jones đã viết về nghiên cứu này trong hai cuốn sách của mình Việc thực hiện các ngôn ngữ lập trình chức năngtriển khai các ngôn ngữ chức năng: một hướng dẫn (phần trước với các phần của Wadler và Hancock, và sau đó được viết bởi David Lester). (Lennart Augowersson cũng thông báo cho tôi rằng một động lực chính cho cuốn sách trước đó là mô tả cách trình biên dịch LML của ông, không được bình luận rộng rãi, đã hoàn thành việc biên soạn nó).

Khái niệm chính đằng sau các phương pháp giảm đồ thị như được mô tả trong các tác phẩm này là chúng tôi không nghĩ chương trình là một chuỗi các hướng dẫn, mà là một biểu đồ phụ thuộc được đánh giá thông qua một loạt các mức giảm cục bộ. Cái nhìn sâu sắc quan trọng thứ hai là việc đánh giá một biểu đồ như vậy không cần phải được diễn giải mà thay vào đó, chính biểu đồ có thể được xây dựng bằng mã . Cụ thể, chúng ta có thể biểu diễn một nút của biểu đồ không phải là "giá trị hoặc" mã "và các giá trị để hoạt động" mà thay vào đó là một hàm khi được gọi, trả về giá trị mong muốn. Lần đầu tiên được gọi, nó yêu cầu các mã con cho các giá trị của chúng và sau đó vận hành trên chúng, và sau đó nó ghi đè lên chính nó bằng một lệnh mới chỉ nói "trả về kết quả.

Điều này được mô tả trong một bài báo sau đó đưa ra những điều cơ bản cho cách GHC vẫn hoạt động cho đến ngày nay (mặc dù có nhiều chỉnh sửa khác nhau): "Thực hiện các ngôn ngữ chức năng lười biếng trên phần cứng chứng khoán: Máy không có thẻ không có thẻ." . Mô hình thực thi hiện tại cho GHC được ghi lại chi tiết hơn tại GHC Wiki .

Vì vậy, cái nhìn sâu sắc là sự phân biệt nghiêm ngặt của "dữ liệu" và "mã" mà chúng tôi nghĩ là "cơ bản" đối với cách thức hoạt động của máy móc không phải là cách chúng phải hoạt động, mà là do trình biên dịch của chúng tôi áp đặt. Vì vậy, chúng ta có thể loại bỏ nó và có mã (trình biên dịch) tạo mã tự sửa đổi (tệp thực thi) và tất cả có thể hoạt động khá độc đáo.

Do đó, hóa ra rằng trong khi kiến ​​trúc máy móc là bắt buộc theo một nghĩa nào đó, các ngôn ngữ có thể ánh xạ tới chúng theo những cách rất đáng ngạc nhiên không giống như điều khiển luồng kiểu C thông thường, và nếu chúng ta nghĩ đủ mức độ thấp, thì điều này cũng có thể Có hiệu quả.

Trên hết, có rất nhiều tối ưu hóa khác được mở ra bởi độ tinh khiết, vì nó cho phép phạm vi biến đổi "an toàn" lớn hơn. Khi nào và làm thế nào để áp dụng những biến đổi này sao cho chúng làm cho mọi thứ tốt hơn và không tồi tệ hơn tất nhiên là một câu hỏi thực nghiệm, và trên điều này và nhiều lựa chọn nhỏ khác, nhiều năm làm việc đã được đưa vào cả công việc lý thuyết và điểm chuẩn thực tế. Vì vậy, điều này tất nhiên cũng đóng một vai trò. Một bài báo cung cấp một ví dụ điển hình cho loại nghiên cứu này là " Tạo ra một món cà ri nhanh: Đẩy / Nhập so với Eval / Áp dụng cho các ngôn ngữ bậc cao".

Cuối cùng, cần lưu ý rằng mô hình này vẫn giới thiệu một chi phí hoạt động do sự gián tiếp. Điều này có thể tránh được trong trường hợp chúng ta biết rằng "an toàn" để thực hiện mọi việc một cách nghiêm ngặt và do đó tránh được các chỉ thị đồ thị. Các cơ chế suy ra tính nghiêm ngặt / nhu cầu một lần nữa được ghi lại trong một số chi tiết tại GHC Wiki .


2
Đó là liên kết phân tích nhu cầu có giá trị trọng lượng của nó bằng vàng! Cuối cùng, một cái gì đó về chủ đề không hoạt động như thể về cơ bản là ma thuật đen không thể giải thích được. Làm thế nào tôi chưa bao giờ nghe nói về điều này ?? Nó nên được liên kết từ mọi nơi mà bất cứ ai hỏi làm thế nào để giải quyết vấn đề với sự lười biếng!
Evi1M4chine

@ Evi1M4chine Tôi không thấy một liên kết liên quan đến máy phân tích nhu cầu, có lẽ nó đã bị mất bằng cách nào đó. Ai đó có thể khôi phục liên kết hoặc làm rõ các tài liệu tham khảo? Nghe có vẻ khá thú vị.
Cris P

1
@CrisP Tôi tin rằng liên kết cuối cùng là những gì đang được đề cập. Nó đi đến một trang trên GHC Wiki về bộ phân tích nhu cầu trong GHC.
Serp C

@Serpentine Cougar, Chris P: Đúng, ý tôi là vậy.
Evi1M4chine

19

Vâng, có rất nhiều bình luận ở đây. Tôi sẽ cố gắng trả lời nhiều nhất có thể.

Được sử dụng một cách chính xác, nó có thể có được các ngôn ngữ cấp thấp.

Theo kinh nghiệm của tôi, thường có thể đạt được hiệu suất gấp đôi so với Rust trong nhiều trường hợp. Nhưng cũng có một số trường hợp sử dụng (rộng) trong đó hiệu suất kém so với các ngôn ngữ cấp thấp.

hoặc thậm chí đánh bại nó, nhưng điều đó có nghĩa là bạn đang sử dụng chương trình C không hiệu quả, vì GHC biên dịch Haskell thành C)

Điều đó không hoàn toàn chính xác. Haskell biên dịch thành C-- (một tập hợp con của C), sau đó được biên dịch thông qua trình tạo mã gốc để lắp ráp. Trình tạo mã gốc thường tạo mã nhanh hơn trình biên dịch C, bởi vì nó có thể áp dụng một số tối ưu hóa mà trình biên dịch C thông thường không thể làm được.

Kiến trúc máy rõ ràng là bắt buộc, dựa trên các máy turing, đại khái.

Đó không phải là một cách tốt để suy nghĩ về nó, đặc biệt là vì các bộ xử lý hiện đại sẽ đánh giá các hướng dẫn không theo thứ tự và có thể cùng một lúc.

Thật vậy, Haskell thậm chí không có một thứ tự đánh giá cụ thể.

Trên thực tế, Haskell không mặc nhiên xác định một trật tự đánh giá.

Ngoài ra, thay vì xử lý các loại dữ liệu máy, bạn luôn tạo các loại dữ liệu đại số.

Chúng tương ứng trong nhiều trường hợp, miễn là bạn có một trình biên dịch đủ nâng cao.

Bạn sẽ nghĩ rằng việc tạo các chức năng một cách nhanh chóng và ném chúng xung quanh sẽ khiến chương trình chậm hơn.

Haskell được biên dịch và do đó, các hàm bậc cao hơn không thực sự được tạo ra một cách nhanh chóng.

Nó dường như để tối ưu hóa mã Haskell, bạn cần làm cho nó thanh lịch và trừu tượng hơn, thay vì nhiều máy như thế.

Nói chung, làm cho mã nhiều hơn "máy như" là một cách không hiệu quả để có được hiệu suất tốt hơn trong Haskell. Nhưng làm cho nó trừu tượng hơn không phải lúc nào cũng là một ý tưởng tốt. Có gì một ý tưởng tốt là sử dụng cấu trúc dữ liệu phổ biến và chức năng đã được tối ưu hóa nặng nề (như danh sách liên kết).

f x = [x]f = purelà điều tương tự chính xác trong Haskell, ví dụ. Một trình biên dịch tốt sẽ không mang lại hiệu suất tốt hơn trong trường hợp trước.

Tại sao Haskell (được biên dịch với GHC) lại nhanh như vậy, xem xét tính chất trừu tượng và sự khác biệt của nó so với các máy vật lý?

Câu trả lời ngắn gọn là "bởi vì nó được thiết kế để làm chính xác điều đó." GHC sử dụng máy g không có thẻ không quay (STG). Bạn có thể đọc một bài báo về nó ở đây (nó khá phức tạp). GHC cũng làm rất nhiều thứ khác, chẳng hạn như phân tích nghiêm ngặt và đánh giá lạc quan .

Lý do tôi nói C và các ngôn ngữ mệnh lệnh khác có phần giống với Turing Machines (nhưng không đến mức Haskell giống với Lambda Compus) là trong một ngôn ngữ bắt buộc, bạn có số lượng trạng thái hữu hạn (còn gọi là số dòng) với một Băng (ram), sao cho trạng thái và băng hiện tại xác định phải làm gì với băng.

Là điểm nhầm lẫn sau đó khả năng biến đổi sẽ dẫn đến mã chậm hơn? Sự lười biếng của Haskell thực sự có nghĩa là khả năng biến đổi không thành vấn đề như bạn nghĩ, cộng với mức độ cao nên có nhiều tối ưu hóa mà trình biên dịch có thể áp dụng. Do đó, việc sửa đổi một bản ghi tại chỗ sẽ hiếm khi chậm hơn so với ngôn ngữ như C.


3

Tại sao Haskell (GHC) rất nhanh?

Một cái gì đó đã thay đổi đáng kể kể từ lần cuối tôi đo hiệu suất của Haskell. Ví dụ:

  • Một điểm chuẩn xử lý tệp RRD trong đó tác giả nhận thấy Haskell mất nhiều thời gian hơn để phát triển và chạy chậm hơn (1.020 giây) so với Go (130s) và OCaml (67 giây), tức là chậm hơn 15 lần so với OCaml.
  • Một điểm chuẩn từ điển đơn giản cho thấy Haskell chạy chậm hơn ~ 10 lần so với F #.
  • Các Ray Tracer Ngôn ngữ So sánh là một ví dụ nơi Haskell là chậm hơn so với C ++, OCaml và thậm chí Java và Lisp.
  • Một quicksort chung song song trong Haskell chậm hơn 55% so với F # và yêu cầu nhiều mã hơn.

Vậy điều gì đã thay đổi? Tôi chú ý hơn cả câu hỏi cũng như bất kỳ câu trả lời hiện tại nào của nó đề cập đến bất kỳ điểm chuẩn có thể kiểm chứng hoặc thậm chí mã.

Một điều yêu thích của Haskeller phải làm là thử và nhận trong vòng 5% C

Bạn có bất kỳ tài liệu tham khảo nào về kết quả có thể kiểm chứng được không, nơi mà bất cứ ai từng đến gần đó?


6
Có ai đó nói tên của Harrop trước gương ba lần nữa không?
Chuck Adams

2
không phải là 10, nhưng vẫn vậy, toàn bộ mục này là tiếp thị cường điệu và tripe. GHC thực sự khá có khả năng đến gần C hoặc thậm chí vượt qua nó đôi khi, về tốc độ, nhưng điều đó thường đòi hỏi một phong cách lập trình cấp thấp, có liên quan không khác nhiều so với lập trình trong chính C. không may. mã càng cao, thông thường càng chậm. rò rỉ không gian, các loại ADT tiện lợi nhưng kém hiệu quả ( đại số , không trừu tượng , như lời hứa), v.v.
Will Ness

1
Tôi chỉ đăng bài này vì tôi thấy nó hôm nay chrispenner.ca/posts/wc . Đây là một triển khai của tiện ích wc được viết bằng Haskell, được cho là đánh bại phiên bản c.
Garrison

3
@Garrison cảm ơn vì đường link . 80 dòng là cái mà tôi gọi là "phong cách lập trình cấp thấp không khác nhiều so với lập trình trong chính C." . "Mã cấp cao hơn", đó sẽ là "ngu ngốc" fmap (length &&& length . words &&& length . lines) readFile. Nếu điều đó nhanh hơn (hoặc thậm chí có thể so sánh với) C, thì sự cường điệu ở đây sẽ hoàn toàn hợp lý sau đó . Chúng ta vẫn cần phải làm việc chăm chỉ cho tốc độ trong Haskell như trong C, là điểm chính.
Will Ness

2
Đánh giá bằng cuộc thảo luận này trên Reddit reddit.com/r/programming/comments/dj4if3/ Khăn rằng mã Haskell thực sự có lỗi (ví dụ: ngắt dòng bắt đầu hoặc kết thúc bằng khoảng trắng, ngắt trên à) và những người khác không thể tái tạo kết quả hiệu suất được yêu cầu.
Jon Harrop
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.