2015-08-25 34 views
5

Xin lỗi vì đã làm phiền bạn với sự cố đơn giản này. Tôi đang cố gắng tìm hiểu cách hoạt động của tiện ích gia đình loại. Khi tôi đánh lừa nó, tôi gặp phải một lỗi mà tôi không thể hiểu tại sao.Lỗi gia đình loại Haskell

class Foo a b c where 
    data T a b c :: * 

    f :: a -> T a b c 

    g :: T a b c -> b 

    h :: c -> a -> b 
    h c a = g $ f a 

Thông báo lỗi:

Could not deduce (Foo a b c0) arising from a use of ‘g’ 
from the context (Foo a b c) 
    bound by the class declaration for ‘Foo’ 
    at DB/Internal/Typecast.hs:(17,1)-(25,19) 
The type variable ‘c0’ is ambiguous 
Relevant bindings include 
    a :: a (bound at DB/Internal/Typecast.hs:25:9) 
    h :: c -> a -> b (bound at DB/Internal/Typecast.hs:25:5) 
In the expression: g 
In the expression: g $ f a 
In an equation for ‘h’: h c a = g $ f a 

Tôi không hiểu thế nào là c mơ hồ trong T a b c cho g. Không thể trình biên dịch nhận được loại c từ số T a b c của f?

Tôi chỉ muốn các hỗn hợp của g . f

+0

Vui lòng sửa sự chú ý trong ví dụ mã của bạn - tức là, đăng mã thực của bạn. Đăng mã khác với những gì bạn đang thực sự sử dụng chỉ obfuscates vấn đề thực tế. – Cubic

+1

"Trình biên dịch có thể lấy kiểu' c' từ 'T a b c' của' f'? " Có, nhưng 'f' lấy' T a b c' từ đâu? –

+0

@DanielWagner Xin lỗi Tôi không nghĩ rằng tôi hiểu cách thức hoạt động của gia đình. Không phải là T a b c trong cả f và g những gì tôi khai báo trong một khai báo cá thể bằng cách sử dụng từ khóa dữ liệu? – Larry

Trả lời

4

Lưu ý rằng trong định nghĩa

h :: c -> a -> b 
h c a = g $ f a 

không có hạn chế mà fg tham khảo các cùng dụ mà bạn đang định h cho. (Và sự linh hoạt này thường rất hữu ích cho việc xác định các trường hợp.)

Từ suy luận kiểu, kết quả của g bị hạn chế là của cùng một loại b, và lập luận của f bị hạn chế là loại a, nhưng không có gì là nói rằng số T a b c được chuyển từ người này sang người khác đang sử dụng cùng một số c!

Để sửa lỗi này trong trường hợp này, bạn có thể bật ScopedTypeVariables và làm

h c a = g (f a :: T a b c) 

Lưu ý rằng việc này vì gia đình dữ liệu là "ánh" (các đối số loại của một gia đình dữ liệu có thể được rút ra từ các loại thức). Nếu bạn đã sử dụng một gia đình thay vào đó, ngay cả điều này sẽ không hoạt động, kể từ đó T a b c sẽ không nhất thiết phải xác định c.

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