2012-04-29 30 views
13

Câu hỏi 1Haskell: hiểu "Không dụ cho" thông báo lỗi trong ghci

Hi, nếu trong WinGHCi Tôi cố ý làm mảnh sai mã sau đây:

3 4 

Sau đó thông báo lỗi tôi get is

<interactive>:1:1: 
    No instance for (Num (a0 -> t0)) 
     arising from the literal `3' 
    Possible fix: add an instance declaration for (Num (a0 -> t0)) 
    In the expression: 3 
    In the expression: 3 4 
    In an equation for `it': it = 3 4 

Chính xác thì No instance for (Num (a0 -> t0)) có nghĩa là gì?

Câu hỏi 2

Tại sao đoạn mã sau:

(+) 2 3 4 
<interactive>:1:7: 
    No instance for (Num (a0 -> t0)) 
     arising from the literal `3' 
    Possible fix: add an instance declaration for (Num (a0 -> t0)) 
    In the second argument of `(+)', namely `3' 
    In the expression: (+) 2 3 4 
    In an equation for `it': it = (+) 2 3 4 

năng suất một lỗi hơi khác nhau từ mảnh thứ hai của mã:

2+3 4 
<interactive>:1:3: 
    No instance for (Num (a1 -> a0)) 
     arising from the literal `3' 
    Possible fix: add an instance declaration for (Num (a1 -> a0)) 
    In the expression: 3 
    In the second argument of `(+)', namely `3 4' 
    In the expression: 2 + 3 4 

Cụ thể trong lần đầu tiên đoạn mã chúng tôi có No instance for (Num (a0 -> t0)) ở đâu trong đoạn mã thứ hai, chúng tôi có No instance for (Num (a1 -> a0)).


[Response to ehird]

(Câu hỏi chuyển từ bình luận câu trả lời):

1) Tôi đánh giá cao hai biểu thức thứ hai là khác nhau, nhưng bạn đang nói rằng tôi không nên cố gắng tìm hiểu tại sao người thông dịch chọn (Num (a0 -> t0)) cho người trước đây và (Num(a1 -> a0)) cho người thứ hai, ngoài thực tế là họ khác nhau?

2) Xin chào, và với trường hợp cũ khi bạn nói "Nhưng không có chữ số Num cho hàm" bạn có ý gì? Xin lỗi tôi không rõ ràng về khái niệm của một cá thể là gì. Hơn nữa, chỉ vì tò mò, bạn có thể sử dụng phương pháp Num (a -> b) dụ của bạn bằng cách nào đó để thông dịch viên cho việc giải thích 3 44 modulo 3?

Trả lời

16

Mục đích của tôi là bổ sung câu trả lời của ehird với một chút giải thích thêm.Khi bạn đã viết các biểu

3 4 

Sau đó, người phiên dịch Haskell nghĩ rằng bạn đang cố gắng áp dụng các chức năng 3 để bất cứ điều gì 4 là. Để cho Haskell để giải thích 3 như một chức năng, nó cần phải thực hiện cuộc gọi đến các chức năng

fromInteger :: Integer -> (a -> b) 

để có được một hàm (ví dụ: một cái gì đó kiểu a -> b) từ nguyên 3. Bây giờ, fromInteger được định nghĩa trong Num typeclass để có chữ ký

instance Num x where 
    fromInteger :: Integer -> x 

tức là khi bạn thực hiện kiểu x một thể hiện của lớp Num, bạn cho một thực hiện fromInteger mà nói Haskell làm thế nào để chuyển đổi một số nguyên đen vào an x. Trong trường hợp của bạn, x là loại chức năng a -> b. Vì vậy, hãy làm điều đó!


Đầu tiên, một số bản mẫu. Để làm x một thể hiện của Num Haskell đòi hỏi chúng ta cũng làm cho nó một thể hiện của ShowEq:

instance Show (a -> b) where show f = "<function>" 
instance Eq (a -> b) where f == g = False 

Bây giờ giả sử chúng ta muốn giải thích 3 4 là "4 modulo 3". Sau đó, chúng ta cần nói cho Haskell cách giải thích bất kỳ số nguyên nào như một hàm gọi là mod. Hơn nữa, vì mod chỉ chấp nhận loại tách rời (nó có chữ ký mod :: Integral a => a -> a -> a) sau đó chúng ta cần phải hạn chế các loại ab là không thể thiếu cũng như:

instance (Integral a, Integral b) => Num (a -> b) where 

Để make an instance of Num chúng ta cần phải cung cấp cho triển khai của (+), (-) , (*)fromIntegral (thực ra chúng ta cũng nên định nghĩa một vài hàm khác, nhưng đừng lo lắng về điều đó ngay bây giờ).

Có một cách khá tự nhiên để xác định cộng, trừ và phép nhân (tất cả các mã từ đây hình thành một phần của Num dụ và cần được thụt vào so với việc kê khai dụ)

f + g = \x -> f x + g x 
    f - g = \x -> f x - g x 
    f * g = \x -> f x * g x 

tức là khi bạn thêm hai chức năng fg, bạn sẽ có một hàm mới áp dụng cả hai đối số fg cho đối số của nó, sau đó thêm chúng lại với nhau. Vì chúng tôi yêu cầu rằng kết quả của việc áp dụng fg là loại không thể thiếu, chúng tôi biết rằng việc thêm kết quả đầu ra của họ là hợp lý.

Để giải thích một số nguyên như là một hàm chúng ta có thể viết

fromInteger n = \m -> fromIntegral m `mod` fromIntegral n 

tức là khi chúng ta có một số nguyên n, chúng tôi trở lại một chức năng của một tham số m đó, khi gọi, đảm bảo rằng cả hai đối số của cùng một loại (bằng cách gọi fromIntegral trên cả hai) và sau đó sử dụng chúng làm đối số cho hàm mod.

Cuối cùng, một chút soạn sẵn để ngăn chặn Haskell phàn nàn:

abs f = undefined 
    signum f = undefined 

Chúng tôi có thể kiểm tra điều này. Tôi có mã của tôi trong một tập tin gọi là numfun.hs. Tôi khởi động phiên dịch Haskell và tải tập tin của tôi:

Prelude> :l numfun.hs 
[1 of 1] Compiling Main    (numfun.hs, interpreted) 
Ok, modules loaded: Main. 

Bây giờ tôi có thể xác định một số chức năng:

*Main> let f = (+ 1) 
*Main> let g = (* 2) 

tôi có thể thêm chúng hoặc trừ họ:

*Main> (f + g) 3 -- (3+1) + (3*2) 
10 
*Main> (f - g) 3 -- (3+1) - (3*2) 
-2 

Và tôi có thể số gọi là chức năng:

*Main> 3 4   -- 4 `mod` 3 
1 
+0

Wow cảm ơn bạn rất nhiều vì lời giải thích chi tiết và được vạch ra rõ ràng này; Tôi rất trân trọng điều này. Tôi nghĩ rằng tôi sẽ cần phải nhấn một số cuốn sách được chỉ định trên trang web Haskell và quay lại bài đăng của bạn một vài lần nữa trước khi tôi tiêu hóa mọi thứ bạn đã viết. Cảm ơn bạn. – artella

14

Lỗi đầu tiên xảy ra vì một số nguyên như 4 có thể thuộc bất kỳ loại nào với phiên bản Num. Đó là, 4 có loại (Num a) => a, vì vậy nó có thể đóng vai trò như một Integer, một Double, một Rational, vv Kể từ khi bạn áp dụng 3 đến một cuộc tranh cãi (4), nó biết rằng, trong bối cảnh, 3 phải là một loại chức năng (tức là a0 -> t0 đối với một số a0t0). Nhưng không có trường hợp Num cho các chức năng, do đó việc sử dụng 3 của bạn làm chức năng không hợp lệ. Nếu bạn đã thêm instance Num (a -> b), nó sẽ hoạt động, nhưng có thể bạn không muốn.

Đối với trường hợp sau, hai thông báo lỗi tương đương; các tên do GHC tạo ra không có ý nghĩa cụ thể. Các chữ cái thường được lấy từ các biến kiểu trong các loại hàm bạn đang sử dụng, và các số được nối thêm để giữ cho mọi thứ rõ ràng. Trong trường hợp này, biểu thức thứ hai tương đương với (+) 2 (3 4) (vì ứng dụng hàm liên kết chặt chẽ hơn bất kỳ toán tử infix nào), nó không hoàn toàn giống với đoạn mã đầu tiên của bạn.

+0

Xin chào, tôi rất biết ơn ăn hai biểu thức sau là khác nhau, nhưng bạn có nói rằng tôi không nên cố gắng hiểu tại sao thông dịch viên chọn '(Num (a0 -> t0))' cho trước và '(Num (a1 -> a0))' cho sau này, bên cạnh thực tế là chúng khác nhau? Cảm ơn. – artella

+0

Xin chào, và với cái cũ khi bạn nói "Nhưng không có Num dụ cho các chức năng" bạn có ý gì? Xin lỗi tôi không rõ ràng về khái niệm của một cá thể là gì. Hơn nữa, chỉ vì tò mò, bạn có thể sử dụng phương thức 'instance Num (a -> b)' bằng cách nào đó nói cho trình thông dịch hiểu '3 4' là' 4 modulo 3 'không? Cảm ơn – artella

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