2012-05-22 40 views
6

tôi có chức năng như sau:chức năng không thể phù hợp với loại

foo :: Int -> a -> [a] 
    foo n v = bar n 
     where 
     bar :: Int -> [a] 
     bar n = take n $ repeat v 

sử dụng báo cáo ghci lỗi này:

Couldn't match type `a' with `a1' 
      `a' is a rigid type variable bound by 
       the type signature for foo :: Int -> a -> [a] at hs99.hs:872:1 
      `a1' is a rigid type variable bound by 
       the type signature for bar :: Int -> [a1] at hs99.hs:875:9 
    Expected type: [a1] 
     Actual type: [a] 
    In the expression: take n $ repeat v 
    In an equation for `bar': bar n = take n $ repeat v 

Nếu loại bỏ các khai báo kiểu của thanh, mã có thể được biên dịch mà không có lỗi. Vì vậy, loại khai báo thích hợp của thanh ở đây là gì? Và tại sao lỗi xảy ra, bởi vì kiểu khai báo của thanh là chung chung hơn định nghĩa của thanh (mà là ràng buộc với một số loại trong foo)?

Cảm ơn bạn đã trợ giúp!

Trả lời

9

Các a trong

foo :: Int -> a -> [a] 

a trong

bar :: Int -> [a] 

là các biến kiểu khác nhau có cùng tên.

Để có được hành vi mà bạn mong đợi, bật phần mở rộng ScopedTypeVariables (ví dụ như bằng cách chèn {-# LANGUAGE ScopedTypeVariables #-} ở phía trên cùng của tập tin nguồn của bạn), và thay đổi kiểu chữ ký của foo để

foo :: forall a. Int -> a -> [a] 

Khi ScopedTypeVariables không được bật, dường như mã ban đầu của bạn được viết như thế này:

foo :: forall a. Int -> a -> [a] 
foo n v = bar n 
    where 
    bar :: forall a. Int -> [a] 
    bar n = take n $ repeat v 

Không đúng khi nói rằng ghci implici tly sử dụng ScopedTypeVariables nếu bạn bỏ chú thích kiểu cho bar.

Thay vào đó, chú thích loại bạn cung cấp cho bar xung đột với loại ghci infers --- bạn đang khẳng định bar có loại ghci biết rằng nó không thể có.

Khi bạn xóa chú thích loại, bạn xóa xung đột.

ScopedTypeVariables thay đổi ý nghĩa của chú thích loại mà bạn cung cấp. Nó không có hiệu lực như thế nào ghc infers loại.

+0

Nhờ sự giúp đỡ! Như tôi đã nói, nếu loại bỏ khai báo kiểu 'bar', ghci có thể biên dịch mã, điều đó có nghĩa là ghci ngầm sử dụng ScopedTypeVariable ở đây cho nó? – Orup

+0

được rõ ràng hơn, phạm vi loại biến và loại bỏ 'thanh' loại tuyên bố cả hai có thể làm cho mã biên dịch. chỉ cần tự hỏi nếu họ đang làm cùng một thủ thuật. – Orup

+0

Không, họ nhận được cùng một mã được biên dịch, nhưng họ nhận được một cách khác nhau. Xem chỉnh sửa của tôi. – dave4420

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