2015-10-13 37 views
6

Tôi đang chơi xung quanh với những cái ôm hôm nay và đã bị mắc kẹt tại một câu hỏi rất đơn giản:Loại (1 2) trong Haskell là gì?

λ 1 1 
:: (Num a, Num (a -> t)) => t 

loại đó sẽ là gì? Tôi gặp khó khăn khi đọc điều này.

Và nếu nó có loại, tại sao? Tôi đoán rằng biểu thức 1 1 bị lỗi và do đó việc kiểm tra kiểu không thành công, được trình biên dịch Haskell hỗ trợ.

Trả lời

12

Không nó không phải là vô hình thành. Loại này là lạ và có lẽ không thể có bất kỳ giá trị có ý nghĩa mà nó có ý nghĩa nhưng nó vẫn được cho phép.

Hãy nhớ rằng các chữ bị quá tải. 1không phải một số nguyên. Đó là loại Num. Các hàm không phải là bị loại trừ khỏi điều này. Không có quy tắc nào nói rằng a -> tkhông thể là "số" (ví dụ: phiên bản Num).

Ví dụ bạn có thể có một tuyên bố instance như:

instance Num a => Num (a -> b) where 
    fromInteger x = undefined 
    [...] 

tại 1 1 sẽ chỉ đơn giản bằng undefined. Không phải rất hữu ích nhưng vẫn hợp lệ.

Bạn có thể có định nghĩa hữu ích của Num cho các chức năng. Ví dụ, từ wiki

instance Num b => Num (a -> b) where 
    negate  = fmap negate 
     (+)   = liftA2 (+) 
     (*)   = liftA2 (*) 
     fromInteger = pure . fromInteger 
     abs   = fmap abs 
     signum  = fmap signum 

Với điều này bạn có thể viết những thứ như:

f + g 

nơi fg là hàm số trở về.

Sử dụng khai báo cá thể trên 1 2 sẽ bằng 1. Về cơ bản, chữ được sử dụng làm hàm với trường hợp trên là bằng const <that-literal>.

+0

Nhân tiện, có bất kỳ ví dụ thực tế nào về một biểu thức như '1 2' hoặc' True 'hello "' hay '" hello "[1,2,3]' vv hữu ích không? DSL tôi đoán? –

+1

'True' không bị quá tải - nó là một hàm tạo thực sự của' dữ liệu Bool = False | True' kiểu dữ liệu – Fraser

+0

@ErikAllik Tôi chưa bao giờ thấy điều này được sử dụng theo cách này. Nó có thể là có thể nhưng AFAIK không được sử dụng. – Bakuriu

5

Trong Haskell, 1 không có loại cố định. Nó là "bất kỳ loại số" nào. Chính xác hơn, bất kỳ loại nào thực hiện lớp Num.

Cụ thể, nó có giá trị về mặt kỹ thuật đối với loại chức năng là phiên bản Num. Không ai có thể làm điều đó, nhưng về mặt kỹ thuật thì có thể.

Vì vậy, trình biên dịch là giả định rằng các đầu tiên1 là một số loại loại chức năng số, và sau đó là thứ hai1 là bất kỳ loại số khác (có thể là cùng loại, có lẽ một khác nhau). Nếu chúng ta thay đổi biểu thức để, nói, 3 6, sau đó trình biên dịch là giả

3 :: Num (x -> y) => x -> y 
6 :: Num x => x 
3 6 :: (Num (x -> y), Num x) => y 
+1

Nó cũng gây ra một chút lộn xộn khi bạn thực hiện chức năng một thể hiện của 'Num', nhưng tôi sẽ không nói rằng không ai sẽ làm điều đó.Nó rất hữu ích trong cùng một nghĩa rằng một thể hiện 'Monoid' của các hàm rất hữu ích: bạn có thể viết ví dụ như' (+5) * (+3) 'và nhận hàm mới' \ x -> (x + 5) * (x + 3) ', tôi nghĩ nó khá tuyệt. Xem thêm tại đây (https://wiki.haskell.org/Num_instance_for_functions). –

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