2009-11-29 28 views
13

Có cách nào để "nâng" một thể hiện lớp trong Haskell dễ dàng không?Ví dụ nâng cấp trong Haskell

Tôi đã thường xuyên cần phải tạo ra, ví dụ, trường hợp Num cho một số lớp học mà chỉ là "nâng" cơ cấu Num thông qua các loại nhà xây dựng như thế này:

data SomeType a = SomeCons a 

instance (Num a)=>Num SomeCons a where 
    (SomeCons x) + (SomeCons y) = SomeCons (x+y) 
    negate (SomeCons x) = SomeCons (negate x) 
    -- similarly for other functions. 

Có cách nào để tránh điều này boilerplate và "nâng" cấu trúc Num này tự động? Tôi thường phải làm điều này với Show và các lớp khác cũng khi tôi đã cố gắng để tìm hiểu existencials và trình biên dịch sẽ không cho phép tôi sử dụng deriving(Show).

Trả lời

19

Các Newtype tổng quát là những gì bạn muốn ở đây:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

module Main where 

newtype SomeType a = SomeCons a deriving (Num, Show, Eq) 

main = do 
    let a = SomeCons 2 
     b = SomeCons 3 
    print $ a + b 

Output:

*Main> main 
SomeCons 5 
+1

Hum ... Tại sao điều này làm việc với Newtype nhưng không phải với dữ liệu? –

+3

Vì một kiểu mới không thể thêm bất kỳ hàm tạo hoặc trường nào — nó chỉ viết lại một kiểu hiện có. Điều này đảm bảo rằng phần mở rộng có thể làm việc với bất kỳ lớp nào, thay vì chỉ các lớp mà bạn thường có thể lấy được cho bất kỳ kiểu dữ liệu nào. – Martijn

5

GHC thực hiện những gì bạn muốn: Extensions to the deriving mecanism. Những thay đổi này thường được hiển thị cho phần mở rộng ngôn ngữ tiêu chuẩn trong tương lai (Như đã thấy trên haskell' wiki)

Để Kích hoạt tính năng mở rộng này, bạn phải sử dụng pragma sau

{-# GeneralizedNewtypeDeriving #-} 

và sau đó sử dụng một bắt nguồn trên khai Newtype của bạn, như thông thường kéo dài bắt nguồn

data SomeType a = SomeCons a deriving (Num) 
1

GeneralizedNewtypeDeriving

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