Tại sao Haskell không thể tránh đánh giá lặp đi lặp lại mà không hạn chế sự đơn hình?


14

Tôi vừa hoàn thành việc học hỏi bạn vào một ngày khác, và tôi đang cố gắng hiểu ý nghĩa của Hạn chế đơn hình, như được mô tả bởi Haskell Wiki . Tôi nghĩ rằng tôi hiểu làm thế nào MR có thể ngăn chặn các đánh giá lặp đi lặp lại, nhưng tôi không biết tại sao những đánh giá lặp đi lặp lại đó không thể tránh được bằng các phương tiện đơn giản hơn nhiều.

Ví dụ cụ thể mà tôi có trong đầu là ví dụ được sử dụng bởi wiki:

f xs = (len,len)
  where
    len = genericLength xs

nơi genericLengthcó loại Num a => [b] -> a.

Rõ ràng, genericLength xschỉ cần được tính toán một lần để đánh giá (len,len), vì đó là cùng một hàm với cùng các đối số. Và chúng ta không cần phải thấy bất kỳ lời mời nào fđể biết điều đó. Vậy tại sao Haskell không thể thực hiện tối ưu hóa này mà không đưa ra quy tắc như MR?

Cuộc thảo luận trên trang wiki đó cho tôi biết nó có liên quan đến thực tế Numlà một kiểu chữ chứ không phải là một kiểu cụ thể, nhưng ngay cả như vậy, không nên rõ ràng vào thời gian biên dịch rằng một hàm thuần sẽ trả về cùng một giá trị- -Và do đó, cùng một loại Num cụ thể - khi được đưa ra cùng một đối số hai lần?

Câu trả lời:


11

Đó là cùng một tên hàm, với cùng các đối số, nhưng có khả năng trả về các kiểu và cách triển khai khác nhau, bởi vì nó là đa hình. Điều đó có nghĩa là nếu nó được gọi trong bối cảnh mong đợi (Int, MyWeirdCustomNumType)kiểu trả về, thì nó phải đánh giá nó hai lần, bởi vì việc thực hiện (+)trong Inthoàn toàn khác với việc thực hiện (+)trong MyWeirdCustomNumType. Bạn cần chạy mã vật lý khác nhau tại một số điểm.

Đó là lý do tại sao nó Numlà một loại lớp. Nó có nghĩa là bạn có các triển khai khác nhau cho các loại khác nhau. Điều đó cũng có nghĩa là nếu ftrong thư viện, nó không biết tại thời điểm biên dịch về tất cả các kết hợp loại mà nó có thể cần trả về.

Vì vậy, vâng, bạn cần phải xem các yêu cầu fđể biết loại trả về sẽ sử dụng. Hầu hết thời gian, bạn sẽ mong đợi chúng giống nhau, đó là lý do tại sao chúng đặt giới hạn đơn hình theo mặc định. Nó có thể được tắt cho những dịp hiếm hoi khi bạn không. Trong thực tế, các lập trình viên không có xu hướng để lại các loại tình huống này để loại suy luận.


Tôi đã không xem xét khả năng f [] :: (Int, Float). Bây giờ nó làm cho ý nghĩa hoàn hảo. Cảm ơn bạn.
Ixrec

1
It's the same function name, with the same arguments, but potentially different return types and implementations, because it's polymorphic.Tôi nghĩ rằng cách tốt hơn để xem xét đó là phiên bản typeclass thực sự là một đối số phụ genericLengthvà trình biên dịch không thuyết phục nó là các đối số tương tự trong cả hai cuộc gọi.
Doval

Câu hỏi phụ nhanh. Nếu MonomorphismRestriction bị tắt, nhưng sau đó bạn đã làm một cái gì đó như a = uncurry (==) $ f [1, 2, 3]nó có thể tối ưu hóa trang web cuộc gọi đó để chỉ kiểm tra độ dài của [1, 2, 3]một lần không? Nếu vậy thì tôi thực sự bối rối không biết những gì hạn chế đơn hình thực sự đang mua cho bạn, nếu không thì tại sao không?
dấu chấm phẩy
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.