2013-02-03 21 views
8

tôi có thể không cho cuộc sống của tôi hiểu tại sao chức năng SML Sau đây là ném một cảnh báo trong vấn đề bài tập về nhà:SML Cảnh báo: Loại Vars Không Generalized khi sử dụng Danh sách rỗng hoặc tùy chọn NONE

fun my_func f ls = 
    case ls of 
    [] => raise MyException 
    | head :: rest => case f head of 
        SOME v => v 
        | NONE => my_func f rest 

fun f a = if isSome a then a else NONE; 

Bất cứ khi nào tôi gọi my_func với các chức năng kiểm tra sau:

my_func f [NONE, NONE]; 
my_func f []; 

tôi luôn luôn nhận được cảnh báo:

chiến ning: Loại VAR không khái quát hóa vì hạn chế giá trị được khởi tạo với các loại hình nộm (X1, X2, ...)

Bất cứ khi nào tôi vượt qua trong một danh sách tùy chọn có chứa ít nhất một số giá trị, Cảnh báo này không phải là ném. Tôi biết nó phải là một cái gì đó để làm với thực tế là tôi đang sử dụng đa hình trong currying chức năng của tôi, nhưng tôi đã hoàn toàn bị mắc kẹt như thế nào để thoát khỏi những cảnh báo.

Vui lòng trợ giúp nếu bạn có bất kỳ ý tưởng nào - cảm ơn bạn trước!

Trả lời

17

Hạn chế giá trị được tham chiếu trong cảnh báo là một trong những điều khó hiểu hơn trong SML, tuy nhiên tôi sẽ cố hết sức để giải thích lý do xảy ra trong trường hợp này và cố gắng hướng bạn đến một số tài nguyên để tìm hiểu hơn.

Như bạn đã biết, SML sẽ sử dụng suy luận kiểu để suy ra hầu hết các loại trong chương trình của bạn. Trong chương trình này, loại my_func sẽ được suy ra là ('a -> 'b option) -> 'a list -> 'b. Như bạn đã lưu ý, đó là một loại đa hình. Khi bạn gọi my_func như thế này

myfunc f [NONE, SOME 1, NONE]; 

... các biến kiểu 'a'b được khởi tạo để int optionint.

Tuy nhiên khi bạn gọi nó mà không có một giá trị như SOME 1 trên

myfunc f [NONE, NONE]; 

Bạn nghĩ gì các biến loại nên được instantiated để? Các loại phải có dạng đa hình - chẳng hạn như 't option't cho tất cả các loại 't. Tuy nhiên, có một giới hạn ngăn chặn các giá trị như thế này để đưa vào các loại đa hình.

SML định nghĩa một số biểu thức dưới dạng giá trị không mở rộng và chỉ những giá trị này có thể có trên các loại đa hình.Đó là:

  • literals (hằng số)
  • biến
  • chức năng biểu thức
  • nhà xây dựng (trừ ref) áp dụng cho các giá trị phi mở rộng
  • một giá trị không phải là mở rộng với một loại chú thích
  • bộ dữ liệu trong đó mỗi trường là giá trị không mở rộng
  • ghi lại nơi mỗi trường là giá trị không mở rộng
  • danh sách đó mỗi lĩnh vực là một giá trị không phải là mở rộng

Tất cả những biểu hiện khác, đáng chú ý chức năng gọi (đó là những gì các cuộc gọi đến my_func là) không thể đa hình. Không thể tham khảo. Bạn có thể tò mò muốn thấy những điều sau đây không làm tăng một cảnh báo:

fn() => my_func f [NONE, NONE]; 

Thay vào đó, các loại suy ra là unit -> 'a. Tuy nhiên, nếu bạn gọi hàm này, bạn sẽ nhận được cảnh báo lần nữa.

Sự hiểu biết của tôi về lý do hạn chế này hơi yếu, nhưng tôi tin rằng vấn đề gốc cơ bản là các tham chiếu có thể thay đổi. Dưới đây là ví dụ tôi đã thực hiện từ trang web MLton được liên kết bên dưới:

val r: 'a option ref = ref NONE 
val r1: string option ref = r 
val r2: int option ref = r 
val() = r1 := SOME "foo" 
val v: int = valOf (!r2) 

Chương trình này không đánh máy theo SML do hạn chế về giá trị. Không phải vì hạn chế giá trị, chương trình này sẽ có lỗi kiểu khi chạy.

Như tôi đã nói, sự hiểu biết của tôi là run rẩy. Tuy nhiên tôi hy vọng tôi đã làm sáng tỏ một chút về vấn đề bạn đã gặp phải, mặc dù tôi tin rằng trong trường hợp của bạn, bạn có thể bỏ qua cảnh báo một cách an toàn. Dưới đây là một số tài liệu tham khảo, bạn nên quyết định bạn muốn đào sâu hơn:

http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html

http://mlton.org/ValueRestriction

(BTW trang MLton là vàng rắn Có rất nhiều ẩn đi ở đây, vì vậy nếu bạn. đang cố hiểu điều gì đó kỳ lạ về SML, tôi khuyên bạn nên tìm kiếm ở đây vì bạn có thể sẽ tăng lên nhiều hơn mức bạn muốn ban đầu)

Vì có vẻ như bạn đang sử dụng SML/NJ, đây là hướng dẫn khá tiện dụng cho er thông điệp ROR và cảnh báo rằng nó sẽ cung cấp cho bạn tại thời gian biên dịch:

http://flint.cs.yale.edu/cs421/smlnj/doc/errors.html

+0

Cảm ơn bạn rất nhiều vì trả lời thông tin của bạn! Tôi sẽ xem xét các tài nguyên được đề xuất của bạn để nghiên cứu thêm và sẽ báo cáo lại nếu tôi tìm cách giải quyết thông báo cảnh báo này. Như bạn đã nói, có thể không có khả năng cho những trường hợp thử nghiệm nào đó trống hoặc chỉ chứa NONE, do tính chất đa hình của chúng. Cảm ơn một lần nữa vì sự giúp đỡ của bạn. – mbear

+0

Không sao, tôi rất vui được giúp đỡ.Một vài điều bạn có thể làm để loại bỏ cảnh báo là (1) chú thích với bất kỳ kiểu nào, làm cho giá trị không còn đa hình tất nhiên: '(my_func f [NONE, NONE]): int' hoặc (2) chỉ nhận cảnh báo này xảy ra khi nhập một giá trị như thế này trong REPL, và có lẽ sẽ không được nâng lên trong một chương trình lớn hơn gọi 'my_func' với các dữ liệu khác. – spacemanaki

+1

Haskell có phiên bản lạ lùng này hay thiếu tài liệu tham khảo có thể thay đổi được không? –