2012-01-17 12 views
6

Bối cảnh: Tôi đang điều tra đệ quy ẩn danh và tôi đang thử thách việc thực hiện khúc dạo đầu mà không sử dụng bất kỳ đệ quy nào được đặt tên chỉ để giúp mọi người ngồi thoải mái trong đầu tôi. Tôi chưa hoàn toàn ở đó, và trên đường đi, tôi đã gặp phải thứ gì đó không liên quan nhưng vẫn thú vị.Các chức năng tương đương tạo ra các kết quả phiên dịch khác nhau

map1  = \f -> \x -> if (tail x) == [] 
         then [f (head x)] 
         else f (head x) : (map1 f (tail x)) 

map2 f x =    if (tail x) == [] 
         then [f (head x)] 
         else f (head x) : (map2 f (tail x)) 

map3 f (x:xs) = if xs == [] then [f x] else f x : (map3 f xs) 

map4 f (x:[]) = [f x] 
map4 f (x:xs) = f x : map4 f xs 

GHC than phiền câu hỏi đầu tiên, tốt với thứ hai và thứ ba và thứ tư là chỉ để cho biết cách chúng có thể được triển khai khác nhau.

*Main> map1 (*2) [1..10] 

<interactive>:1:15: 
    No instance for (Num()) 
     arising from the literal `10' 
    Possible fix: add an instance declaration for (Num()) 
    In the expression: 10 
    In the second argument of `map1', namely `[1 .. 10]' 
    In the expression: map1 (* 2) [1 .. 10] 
*Main> map2 (*2) [1..10] 
[2,4,6,8,10,12,14,16,18,20] 
*Main> map3 (*2) [1..10] 
[2,4,6,8,10,12,14,16,18,20] 
*Main> map4 (*2) [1..10] 
[2,4,6,8,10,12,14,16,18,20] 

Nếu tôi thêm chữ ký loại vào bản đồ 1 thì tất cả đều tốt.

map1 :: Eq a => (a -> b) -> [a] -> [b] 

Hai hàm đầu tiên có vẻ khá giống với tôi, vì vậy tôi cho rằng câu hỏi của tôi đơn giản là "Có gì đang diễn ra ở đây?"

+2

Tôi không chắc chắn nếu bạn có lý do cụ thể để viết theo cách này. Tại sao bạn không sử dụng [] làm trường hợp cơ sở cho đệ quy thay vì (x: [])? Không có chức năng nào của bạn sẽ hoạt động với danh sách trống. –

Trả lời

12

Bạn bị cắn bởi . Bất cứ điều gì được viết là foo = ... - có nghĩa là không có đối số nào cho định nghĩa và không có loại rõ ràng nào được đưa ra - phải có loại không chung chung theo giới hạn này. Loại chung trong trường hợp này, như bạn đã nói, phải là Eq a => (a -> b) -> [a] -> [b], nhưng do hạn chế đơn lẻ áp dụng, cả hai ab được thay thế bằng (), loại đơn giản nhất có thể được suy ra cho các biến loại có sẵn.

6

Nhưng, nếu bạn sử dụng không bị giới hạn null thay vì (== []),

Prelude> let map0 = \f -> \x -> if null (tail x) then [f (head x)] else f (head x) : map0 f (tail x) 
Prelude> :t map0 
map0 :: (a -> t) -> [a] -> [t] 
Prelude> map (*2) [1 .. 10] 
[2,4,6,8,10,12,14,16,18,20] 

nó hoạt động không có đối số hoặc chữ ký. Chỉ các biến loại bị ràng buộc phải tuân theo giới hạn monomorphism.

Và nếu bạn đặt định nghĩa của map1 vào một tập tin và cố gắng để biên dịch nó hoặc tải nó vào ghci,

Ambiguous type variable `a0' in the constraint: 
    (Eq a0) arising from a use of `==' 
Possible cause: the monomorphism restriction applied to the following: 
    map1 :: forall t. (a0 -> t) -> [a0] -> [t] (bound at Maps.hs:3:1) 
Probable fix: give these definition(s) an explicit type signature 
       or use -XNoMonomorphismRestriction 
In the expression: (tail x) == [] 
In the expression: 
    if (tail x) == [] then 
     [f (head x)] 
    else 
     f (head x) : (map1 f (tail x)) 
In the expression: 
    \ x 
    -> if (tail x) == [] then 
      [f (head x)] 
     else 
      f (head x) : (map1 f (tail x)) 

ghci chỉ phàn nàn trong cách nó đã làm vì nó sử dụng ExtendedDefaultRules, nếu không bạn sẽ phải nhận được một thông báo lỗi dễ hiểu.