Các loại tổng - Tại sao trong Haskell là `show (Int | Double)` khác với` (show Int) | (hiển thị gấp đôi) `


9

Tại sao những điều này không tương đương?

show $ if someCondition then someInt else some double

if someCondition then show someInt else show someDouble

Tôi hiểu rằng nếu bạn tách riêng if ... elsephần trong ví dụ đầu tiên thành một biểu thức thì bạn không thể biểu diễn kiểu của nó bằng loại tổng ẩn danh, loại Int | Double, giống như một thứ bạn có thể làm dễ dàng trong TypeScript (đề cập đến TypeScript vì đó là langauge tôi đã sử dụng thường xuyên và hỗ trợ các loại Sum) và sẽ phải sử dụng Eitherdữ liệu sau đó dựa trên dữ liệu đó show.

Ví dụ tôi đưa ra ở đây là tầm thường nhưng với tôi nó có ý nghĩa hơn khi nghĩ rằng "Được rồi, chúng tôi sẽ trình bày một cái gì đó, và cái gì đó phụ thuộc vào someCondition" chứ không phải là "Được rồi nếu một số điều kiện là đúng thì hiển thị một số cách khác" và cũng cho phép để sao chép mã ít hơn (ở đây chương trình được lặp lại hai lần nhưng nó cũng có thể là một ứng dụng chức năng dài và thay vì if ... elsecó thể có> 2 nhánh để xem xét)

Trong suy nghĩ của tôi, trình biên dịch sẽ dễ dàng kiểm tra xem mỗi loại tạo ra loại tổng (ở đây Int | Double) có thể được sử dụng làm tham số cho showhàm hay không và quyết định xem các loại có đúng hay không. Thậm chí tốt hơn là showhàm luôn trả về stringbất kể các loại tham số, vì vậy trình biên dịch không phải mang theo tất cả các "nhánh" có thể (vì vậy tất cả các loại có thể).

Có phải do sự lựa chọn mà một tính năng như vậy không tồn tại? Hay là thực hiện nó khó hơn tôi nghĩ?


2
An if ... then ... else ..., cần phải có cùng loại trong thenelsemột phần. Bạn có thể thấy nó như là một toán tử ternary trong một số ngôn ngữ lập trình.
Willem Van Onsem

1
Tôi đồng ý về making all conversions explicit. Trong câu hỏi của tôi, tôi không muốn Haskell bỏ Intqua một Doublehoặc ngược lại. Tôi chỉ sử dụng hai loại đó làm ví dụ. Bạn có thể thay thế tất cả Intvới aDoublevới btrong câu hỏi của tôi, nơi cả hai loại lấy được Show. Tôi hiểu rằng không có anonymous sum typestrong Haskell nhưng tôi muốn biết tại sao lại như vậy và điều gì ngăn cản chúng tôi thiết kế ngôn ngữ để có nó.
Mehdi Saffar

4
Tôi nghĩ những loại như vậy được gọi là loại công đoàn . Một loại tổng về cơ bản là một biến thể được gắn thẻ của loại kết hợp, trong đó mỗi giá trị phải mang một thẻ trái / phải vượt quá giá trị của loại bên trong. Tôi hy vọng kiểu suy luận đó với các loại kết hợp, với tất cả các tính năng cấp độ của Haskell là rất khó để đạt được. Nếu x :: Int | Boolvà chúng ta phải biên dịch show x, không có cách nào dễ dàng để biết sử dụng chức năng con trỏ nào để gọi show, trong RTS dựa trên kiểu xóa. Có lẽ chúng ta cần giữ một số thông tin cấp độ trong thời gian chạy.
chi

1
Không có các loại tổng ẩn danh là một quyết định thiết kế của các nhà thiết kế Haskell. Tôi không chắc chắn họ sẽ mang lại lợi ích gì cho bàn, tôi sẽ thấy họ sẽ làm phức tạp mọi thứ ở đâu. Vì vậy, tôi đoán là họ bị bỏ rơi vì tỷ lệ chi phí / lợi ích là không có. Nhưng để hoàn toàn chắc chắn, bạn cần phải hỏi các nhà thiết kế ngôn ngữ gốc và / hoặc người bảo trì hiện tại. Tôi không nghĩ rằng nó sẽ tạo ra một câu hỏi SO tuyệt vời, bởi vì có rất nhiều ý kiến ​​cá nhân và thị hiếu liên quan đến việc thiết kế một ngôn ngữ.
n. 'đại từ' m.

4
(String, Int)không ẩn danh Nó chỉ là một loại sản phẩm thông thường với cú pháp vui nhộn. (String | Int)sẽ là rất nhiều khác nhau. Bắt đầu với việc tự hỏi liệu có (Int|Int)nên giống hệt Intvà tại sao.
n. 'đại từ' m.

Câu trả lời:


8

Tất cả các phần của một biểu thức phải được gõ tốt. Kiểu if someCondition then someInt else someDoublesẽ phải giống như thế exists a. Show a => a, nhưng Haskell không hỗ trợ kiểu định lượng tồn tại đó.

Cập nhật: Như chi chỉ ra trong một nhận xét , điều này cũng có thể xảy ra nếu Haskell có hỗ trợ cho các loại kết hợp / giao cắt (không giống với các loại tổng / sản phẩm), nhưng thật không may.


Bạn có thể giải thích rõ hơn về sự khác biệt giữa các loại kết hợp / giao lộ và các loại tổng / sản phẩm không? Tôi đã luôn nghĩ rằng họ giống nhau, ngoại trừ ẩn danh?
Mehdi Saffar

1
@MehdiSaffar Ẩn danh như trong unagged, không phải như trong một nhà xây dựng không tên. Nói cách khác, nếu bạn có một Int ∪ Double, thì bạn sẽ biết bạn có một trong hai, nhưng sẽ không thể tạo mẫu khớp để xem cái nào, vì vậy bạn chỉ có thể làm những việc hợp lệ để làm cho cả hai khả năng.
Joseph Sible-Phục hồi Monica

2
Để rõ ràng, TypeScript có thông tin loại có sẵn trong thời gian chạy, do đó, nó có một typeoftoán tử có thể bù cho việc thiếu gắn thẻ và xem loại nào được sử dụng bằng mọi cách. Haskell đã bị xóa hoàn toàn, vì vậy nếu nó hỗ trợ tính năng này, thì sẽ không có bất kỳ tương đương nào.
Joseph Sible-Phục hồi Monica

7

Có các loại sản phẩm với cú pháp nhẹ, được viết (,), bằng Haskell. Một điều sẽ là một loại tổng hợp với một cú pháp nhẹ, đại loại như (Int | String), sẽ là một ý tưởng tuyệt vời. Thực tế phức tạp hơn. Hãy xem tại sao (tôi đang dùng một số quyền tự do Num, chúng không quan trọng).

if someCondition then 42 else "helloWorld"

Nếu điều này sẽ trả về một giá trị của loại như thế (Int | String), thì sau đây nên trả về cái gì?

if someCondition then 42 else 0

(Int | Int)rõ ràng, nhưng nếu điều này khác với đồng bằng Intthì chúng ta sẽ gặp rắc rối lớn. Vì vậy (Int | Int)nên đồng nhất với đồng bằng Int.

Người ta có thể thấy ngay rằng đây không chỉ là cú pháp nhẹ cho các loại tổng, mà là một tính năng ngôn ngữ hoàn toàn mới. Một loại hệ thống khác nếu bạn muốn. Chúng ta có nên có một cái không?

Chúng ta hãy xem chức năng này.

mysteryType x a b = if x then a else b

Bây giờ loại nào mysteryTypecó? Chắc chắn

mysteryType :: Bool -> a -> b -> (a|b)

đúng? Bây giờ nếu abcùng loại thì sao?

let x = mysteryType True 42 0

Điều này nên đơn giản Intnhư chúng ta đã đồng ý trước đây. Bây giờ mysteryTypeđôi khi trả về một loại tổng ẩn danh, và đôi khi không, tùy thuộc vào những đối số bạn vượt qua. Làm thế nào bạn sẽ mô hình phù hợp với một biểu thức như vậy? Bạn có thể làm gì với nó? Ngoại trừ những thứ tầm thường như "hiển thị" (hoặc bất kỳ phương thức nào của các loại lớp khác, nó sẽ là một ví dụ), không phải là toàn bộ. Trừ khi bạn thêm thông tin loại thời gian chạy vào ngôn ngữ, nghĩa typeoflà có sẵn - và điều đó làm cho Haskell trở thành một ngôn ngữ hoàn toàn khác.

Vì vậy, vâng. Tại sao Haskell không phải là một TypeScript? Bởi vì chúng tôi không cần TypeScript khác. Nếu bạn muốn TypeScript, bạn biết nơi để tìm nó.


1
@MichaWiedenmann Thành thật mà nói tôi không biết "có liên quan" là từ đúng hay không. Tôi nghĩ rằng nó hữu ích theo cách này hay cách khác. Có, tôi đã dừng lại một chút và suy nghĩ có bao gồm nó không. Nhưng đôi khi tôi biết là sai.
n. 'đại từ' m.

Không có vấn đề, bài viết của bạn, bạn quyết định.
Micha Wiedenmann

Vậy đại từ của bạn là gì?
dfeuer
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.