2015-06-02 13 views
13

Tôi gặp sự cố liên quan đến hệ thống kiểu Haskell. Đây không phải là lần đầu tiên tôi gặp phải những hạn chế của hệ thống kiểu. Tôi sẽ bỏ qua chi tiết dự án của tôi và sử dụng một ví dụ đơn giản. Dưới đây là một số mã:Haskell: Có thể nhập các biến được sử dụng trong định nghĩa hàm không?

-- Works 
foo :: (Bounded a, Enum a) => a 
foo = minBound 

-- "ambiguous" constraint: 
-- 'a' has no occurrences in type declaration 
bar :: (Bounded a, Enum a) => Int 
bar = fromEnum minBound 

-- Too much information in return 
-- but I can show haskell the appropriate type of 'min' 
baz :: (Bounded a, Enum a) => (a, Int) 
baz = let min = minBound 
    in (min, someFunction . fromEnum $ min) 

-- Type constraint 'a' not ambiguous 
--  (or at least that isn't the compiler error message) 
-- but Haskell doesn't know which 'minBound' to use 
barrer :: (Bounded a, Enum a) => a 
barrer = let min = minBound -- <- min's type is ambiguous 
    in toEnum . someFunction . fromEnum $ min 

Những gì tôi đang cố gắng để đạt được cũng tương tự như barrer: Thứ nhất, sử dụng giá trị minBound cụ gõ a và 'đúc' nó sang một số nguyên. Trong dự án của tôi, tôi tiến hành chuyển đổi số nguyên này (để tránh số học trung gian tràn khi sử dụng loại a) và 'truyền' chúng trở lại loại a (sau một chút ma thuật mod). Làm thế nào tôi có thể nói cho Haskell loại thích hợp của minBound? Có thể không?

Giải pháp hiển nhiên là thêm chú thích minBound :: a. Điều này cũng sẽ sửa lỗi bar. Vấn đề: Biến loại a dường như nằm ngoài phạm vi trong định nghĩa hàm, khi Haskell làm mới minBound :: a đến minBound a0 trong thông báo lỗi. Có cách nào để thực hiện loại chú thích này không?

Một lỗi xấu mà tôi đã sử dụng là hạn chế loại cuộc gọi minBound bằng cách đưa nó vào loại trả về của hàm, a la baz. Giải pháp này không lý tưởng. Có ai có lời khuyên nào không?

Trả lời

14

Phần mở rộng ScopedTypeVariables giải quyết chính xác vấn đề của bạn. Trang cũng cung cấp một số giải pháp thay thế (asTypeOfundefined đối số).

+0

"Biến kiểu phạm vi" - Chính xác những gì tôi muốn. Và nói ngắn gọn hơn nhiều so với tiêu đề của tôi! – bimmo

+0

Làm thế nào bạn thậm chí sẽ làm điều này với asTypeOf và không xác định? Dường như với tôi rằng bạn không bao giờ có thể nhận được một giá trị của loại 'a' để trỏ asTypeOf tại, bởi vì không ai được truyền vào hoặc trả về từ hàm này. Bạn chỉ có thể nắm giữ một thông qua các biến kiểu phạm vi, tại thời điểm đó bạn không còn cần asTypeOf hoặc không xác định. – amalloy

+2

@amalloy Bởi vì 'asTypeOf' không bao giờ thực sự đánh giá đối số thứ hai của nó, chỉ cần sử dụng nó cho suy luận kiểu, bạn có thể buộc nó thành các nút như sau:' 'barrer = let min = minBound' asTypeOf' result; result = toEnum. someFunction. fromEnum $ min trong kết quả'' –

Các vấn đề liên quan