Là hệ thống loại của Haskell là một trở ngại để hiểu lập trình chức năng? [đóng cửa]


33

Tôi đang học Haskell với mục đích tìm hiểu lập trình chức năng, với mong muốn tôi sẽ áp dụng cái nhìn sâu sắc mà tôi có được bằng các ngôn ngữ khác (chủ yếu là Groovy, Python, JavaScript.)

Tôi chọn Haskell vì tôi có ấn tượng rằng nó rất đơn thuần là chức năng và sẽ không cho phép bất kỳ sự phụ thuộc nào vào trạng thái.

Tôi đã không chọn học Haskell vì tôi thích điều hướng một hệ thống loại cực kỳ cứng nhắc.

Câu hỏi của tôi là: Hệ thống loại mạnh có phải là sản phẩm phụ cần thiết của ngôn ngữ chức năng cực kỳ thuần túy hay đây là một lựa chọn thiết kế không liên quan cụ thể với Haskell?


6
Nếu bạn không muốn gõ rõ ràng bất cứ điều gì, bạn không cần phải gõ rõ ràng bất cứ điều gì. Haskell có thể tự suy luận ra các loại tốt. Và không giống như bạn sẽ có một biến duy nhất có khả năng lưu trữ hai loại không tương thích.
Anon.

4
@Anon có, nhưng danh sách của bạn phải đồng nhất. Tin tôi đi, loại chuyện này có thể cản trở, ngay cả với kiểu suy luận.
Eric Wilson

13
@FarmBoy và có gì sai khi sử dụng Có lẽ? Java thực sự khiến bạn sử dụng Có thể trên tất cả các lớp, đó là điều kỳ lạ để làm.
thay thế

3
Và nếu bạn thực sự muốn sử dụng một danh sách không đồng nhất, tất nhiên bạn có thể sử dụng các kiểu dữ liệu đại số.
thay thế

1
@mathepic tại thời điểm này, chúng tôi đã thực sự mất dấu câu hỏi ban đầu của tôi, đó là một câu hỏi hoàn toàn hợp lệ.
Eric Wilson

Câu trả lời:


40

Tôi tin rằng việc hiểu hệ thống loại của Haskell là một bộ khuếch đại để hiểu lập trình chức năng.

Vấn đề của lập trình chức năng thuần túy là trong trường hợp không có tác dụng phụ, cho phép bạn thực hiện tất cả mọi thứ một cách ngầm định, lập trình chức năng thuần túy làm cho cấu trúc chương trình của bạn rõ ràng hơn nhiều.

Haskell ngăn bạn đẩy những thứ dưới thảm, buộc bạn phải xử lý rõ ràng cấu trúc chương trình của bạn và nó dạy cho bạn một ngôn ngữ để mô tả các cấu trúc này: ngôn ngữ của các loại. Hiểu các loại, đặc biệt là các loại phong phú như Haskell, sẽ giúp bạn trở thành một lập trình viên tốt hơn trong bất kỳ ngôn ngữ nào.

Nếu Haskell không được gõ mạnh, các khái niệm như đơn nguyên, chức năng ứng dụng và tương tự sẽ không bao giờ được áp dụng cho lập trình.


2
Đây là một câu trả lời hay, bổ sung của tôi là mặc dù lúc đầu hệ thống có vẻ không bình thường, nhưng sau này khi bạn bắt đầu học các khái niệm nâng cao hơn, bạn sẽ thấy rằng có một số điều chỉ có thể được thực hiện do tuân thủ loại đó hệ thống (thêm STM và Dữ liệu song song vào danh sách trên). Những thứ sẽ không khởi động trong các hệ thống loại khác phù hợp tự nhiên với hệ thống Haskell. Lời khuyên của tôi: hãy kiên trì một thời gian, hãy để nó chìm dần theo thời gian (đó không phải là ngôn ngữ "nhồi nhét").
anon

2
Tôi biết rằng đây là một câu trả lời siêu cũ, nhưng tôi thực sự không đồng ý. Tôi nghĩ rằng, rõ ràng như một số thứ có thể có trong ngôn ngữ, hệ thống loại, đặc biệt là với các đơn nguyên như Bang và Parsec, quét một TẤN thứ dưới thảm. Điều này thực sự can thiệp rất nhiều vào khả năng học các thư viện ngôn ngữ của tôi.
Savanni D'Gerinel

4
@ SavanniD'Gerinel: Tôi nghĩ trong câu trả lời này "xô những thứ dưới thảm" không có nghĩa là thêm chức năng ngầm (mà Haskell thực hiện theo cách được kiểm soát, ví dụ như thông qua các đơn vị, và giúp giảm bớt phần mềm) làm một cái gì đó nó không được mong đợi để làm. Ví dụ: một chức năng thuần túy trong Haskell sẽ không bao giờ có tác dụng phụ. Giai đoạn. Trong nhiều ngôn ngữ khác, bạn có thể hứa điều này trong tài liệu của hàm, nhưng không có gì trong ngôn ngữ của bạn sẽ khiến bạn không thể sử dụng một số tác dụng phụ ở đâu đó trong mã của bạn.
Giorgio

33

Ngôn ngữ chức năng được gõ động nhất là Scheme. Điều đó nói rằng, hệ thống loại của Haskell là một chỉ số về độ tinh khiết của nó. Đó là một câu hỏi về "làm thế nào để đo lường độ tinh khiết?". Hệ thống loại của Haskell cho phép bạn dễ dàng loại bỏ các hành động không trong sạch IO. Để làm điều đó, bạn cần một hệ thống kiểu tĩnh.

Nhưng hãy nói rằng hệ thống loại của Haskell không liên quan gì đến lập trình chức năng. Nó vẫn sẽ là chiều cao của sự kiêu ngạo khi tuyên bố rằng hệ thống loại sẽ không giúp bạn trong nỗ lực giáo dục này. Hệ thống loại của Haskell rất phong phú và phức tạp, và tất cả đều thú vị hơn khi so sánh với các hệ thống loại của C ++ và OCaml.

Có phải là một trở ngại? Không, tôi nghĩ đó là một tài sản. Cố gắng xem xét làm thế nào để đối phó với sự lười biếng của Haskell mà không có IOví dụ.


8
Hệ thống loại +1 của Haskell có thể là bạn của bạn sau khi bạn quen với nó.
Larry Coleman

"Để làm điều đó, bạn cần một hệ thống kiểu tĩnh". Có thật không?
Jon Harrop

1
"Tất cả đều thú vị hơn khi so sánh với các hệ thống loại C ++ và OCaml". Bạn đã nghiên cứu các mô-đun bậc cao thứ nhất của OCaml và cấu trúc hệ thống đối tượng được suy luận và các biến thể đa hình?
Jon Harrop

2
@JonHarrop hoặc một hệ thống hiệu ứng hoặc một số cách đo / đánh giá độ tinh khiết. Đúng, đó là lý do tại sao nó thú vị để so sánh chúng. Sự lựa chọn khác nhau làm cho các ngôn ngữ khác nhau.
Logan Capaldo

20

Clojure được gõ động và gần như thuần túy như Haskell, do đó, có một lập luận tốt rằng hệ thống loại của Haskell là một lựa chọn thiết kế hơn là một yêu cầu tuyệt đối. Cả hai chắc chắn đều có điểm mạnh, vì vậy bạn có thể muốn xem xét Clojure nếu bạn thực sự không thích sự cứng nhắc của Haskell (nhưng xem bên dưới).

Khi tôi lần đầu tiên bắt đầu sử dụng Haskell, tôi đã coi hệ thống loại là gây phiền nhiễu và chỉ chấp nhận nó vì suy luận kiểu. Tôi sớm phát hiện ra rằng nhiều lỗi loại trình biên dịch đã phàn nàn về những thứ không hoạt động được ngay cả khi trình biên dịch đã để tôi thực hiện chúng (ví dụ như vô tình sử dụng bản đồ thay vì concatMap). Sau đó tôi phát hiện ra rằng các chương trình vượt qua kiểm tra loại thường đúng hoặc ít nhất là gần đúng. Tôi thậm chí đã có một giai đoạn lười biếng khi tôi thực hiện tái cấu trúc bằng cách thay đổi một loại hàm và để trình biên dịch cho tôi biết những gì khác cần phải thay đổi. Cuối cùng, tôi nhận ra rằng hệ thống loại của Haskell thực sự rất biểu cảm và bắt đầu thiết kế các chương trình của tôi xung quanh các loại. Đó là Chén Thánh của Haskell.


Một điều khác cần lưu ý: Tôi đã học lập trình chức năng bằng cách sử dụng cả Scheme và Haskell cùng một lúc (cái trước cho một lớp và cái sau cho vui). Tôi thấy rằng việc hiểu đệ quy dễ dàng hơn nhiều với khớp mẫu của Haskell so với ifs và conds trong Scheme, mà tôi tưởng tượng cũng mang đến Clojure.
Tikhon Jelvis

@Larry Coleman: +1 để mô tả chính xác trải nghiệm của riêng tôi với các loại hệ thống: đầu tiên là C ++, sau đó là Ocaml, và bây giờ là ngôn ngữ của riêng tôi. Có, tôi vẫn tái cấu trúc bằng cách theo đuổi các lỗi biên dịch.
Yttrill

8

Hệ thống loại của Haskell là chìa khóa cho khả năng cô lập các hiệu ứng từ mã thuần. Trừ khi bạn có thể cô lập các hiệu ứng theo cách khác hoặc bạn loại bỏ hoàn toàn các hiệu ứng, một hệ thống kiểu tĩnh mạnh là một yêu cầu cho lập trình chức năng thuần túy.

Haskell là một ví dụ rất hay về một ngôn ngữ có hệ thống kiểu tĩnh, mạnh. Nếu bạn muốn có một nền giáo dục rộng và tròn về khoa học máy tính và thiết kế ngôn ngữ lập trình nói riêng, Haskell sẽ là một lựa chọn tuyệt vời là một trong những ngôn ngữ mà bạn nên học.

Hệ thống loại không phải là một trở ngại lớn. Những người lập trình có xu hướng, ngay cả khi sử dụng ngôn ngữ động, tuân theo các quy ước gõ có thể được mã hóa bằng hệ thống loại của Haskell. Haskell cũng có tính năng suy luận kiểu làm giảm bớt tính dài dòng khi so sánh với các ngôn ngữ như C ++ và Java. Khi bạn nhận được thông báo lỗi, trình biên dịch chỉ cho bạn biết tại thời điểm biên dịch những ngôn ngữ có kiểu động sẽ cho bạn biết khi chạy.

Đối lập với hệ thống kiểu động là hệ thống kiểu tĩnh, không phải hệ thống kiểu mạnh. Một hệ thống loại mạnh thì ngược lại với hệ thống loại yếu.


1
Ví dụ, C là tĩnh nhưng gõ yếu. Bạn có các loại, nhưng thật dễ dàng để lật đổ hoàn toàn hệ thống kiểu, chơi xung quanh với các biểu diễn cụ thể của máy bên dưới, v.v.
Steve314

4

Nó cho bạn biết ngay lập tức khi bạn mắc lỗi ngu ngốc. Điều này rất hữu ích. Tôi đã làm việc trong Vợt (Scheme) trong học kỳ vừa qua, và đã có một số lần tôi đã vượt qua một s-exp chưa được chỉnh sửa, nơi tôi mong đợi một ast được phân tích cú pháp cho một số chức năng trong trình thông dịch của tôi, và nó chỉ xuất hiện trong bộ thử nghiệm cỡ trung bình. Nếu tôi có một số gõ tĩnh, nó sẽ được chú ý ngay lập tức.

Tất nhiên, các lỗi logic thực sự không thể bị bắt bởi hệ thống loại, nhưng số cách mà bạn có thể làm hỏng được giảm đi rất nhiều.

Đồng thời, suy luận kiểu cho phép bạn bỏ qua hệ thống loại nếu bạn muốn. Nó vẫn ở đó, nhưng nó không yêu cầu đầu vào hoạt động từ phía bạn. Vẫn hữu ích để hiểu các loại chức năng của bạn, nhưng mã chính xác sẽ hoạt động tốt.

Độ tinh khiết của Haskell được mã hóa trong hệ thống loại của nó. Đơn vị IO là một cấu trúc mức loại ngăn chặn mã không tinh khiết rò rỉ vào các hàm thuần túy, vì vậy độ tinh khiết được đảm bảo bởi hệ thống loại.


8
Nếu bạn nghĩ rằng bạn có thể bỏ qua hệ thống loại của Haskell, thì tôi nghĩ bạn đã mã hóa nhiều Haskell.
Eric Wilson

Không bỏ qua quá nhiều như bỏ qua nó nhiều như gõ hàm, tải nó trong GHCi và đi: t trên nó. Nhưng đôi khi bạn vẫn cần phải rắc một số chức năng từIntegral hoặc các chức năng khác.
Theo Belaire

1
Tyr, ngay cả với suy luận kiểu, 90% việc sử dụng và mã hóa các hàm Haskell đang khiến những thứ đáng nguyền rủa kết nối với nhau, điều này đòi hỏi sự hiểu biết về hệ thống loại của nó và các thông báo lỗi đánh máy phức tạp. Ngay cả ": t" không phải là một giải pháp kỳ diệu, chỉ là bước đầu tiên để hiểu cách biên dịch chương trình.
Andres F.

Vâng, một số phần là lộn xộn, tôi đồng ý. Tôi thực sự nghĩ rằng các công cụ số trong khúc dạo đầu có thể được dọn dẹp và sửa chữa, bởi vì khi nó đứng, đó là một mớ hỗn độn khủng khiếp. Nhưng hầu hết các khía cạnh chức năng chính là khá sạch sẽ. ánh xạ, bộ lọc, Foldr / l và các chức năng chức năng thú vị khác hoạt động khá độc đáo.
Theo Belaire

2

Là một ngôn ngữ "chức năng", có nghĩa là (ngoài những thứ khác) mà các chức năng là các đối tượng hạng nhất trong ngôn ngữ.

Là một ngôn ngữ "thuần túy" có nghĩa là các hàm là các hàm toán học (trái ngược với các thủ tục) - với cùng một đầu vào, chúng luôn tạo ra cùng một đầu ra.

Một "ngôn ngữ chức năng thuần túy" là một ngôn ngữ mà cả hai bên trên đều nắm giữ. Tôi không phải là nhận thức của một "pure- ly ngôn ngữ chức năng".

Một hệ thống loại mạnh là một cách sạch sẽ để có một ngôn ngữ thuần túy nhưng thực tế. Các loại giúp trình biên dịch tìm ra tối ưu hóa, ngoài hình thức tiếp tục đảm bảo tính chính xác. (Nhưng, đó không phải là cách duy nhất - clojure là thuần túy, nhưng không có hệ thống loại mạnh như Haskell.)

Nếu hệ thống loại làm phiền bạn, tôi khuyên bạn nên thử một ngôn ngữ năng động hơn, như Scheme hoặc sử dụng hệ thống suy luận kiểu của Haskell.


0

Vâng, hệ thống loại là một tài sản đáng kinh ngạc. Thậm chí sẽ rất khó để mô tả cách thức các đơn nguyên hoạt động hoặc cách một số tổ hợp hoạt động mà không có hệ thống loại. Xem xét có bao nhiêu hướng dẫn trên Haskell trước tiên yêu cầu bạn xem xét loại hàm được đề cập với a: t tại REPL. Điều đó chỉ đơn giản là không có sẵn cho bạn trong một ngôn ngữ gõ động. Chắc chắn, tất cả sự phức tạp của hệ thống loại vẫn còn đó. Một đơn nguyên vẫn là một đơn nguyên. Nhưng ngôn ngữ đã quyết định rửa tay về vấn đề này và không cung cấp bất kỳ trợ giúp nào cả. Bạn đang ở một mình, bạn thân. Tôi không gõ các ngôn ngữ gõ động. Tôi yêu họ rất nhiều. Đề án là một công cụ quyền lực tuyệt vời. Nhưng bạn sẽ nhận thấy rằng khi chúng ta nói về những thứ như đơn nguyên bằng ngôn ngữ động, chúng ta thường phát minh ra một ký hiệuđể mô tả các loại thủ tục. Một lập trình viên chức năng sẽ chiến đấu với các loại cách này hay cách khác. Trình kiểm tra loại của Haskell chỉ cung cấp cho bạn các công cụ tốt để tìm hiểu cách thực hiện điều đó.

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.