2015-09-24 17 views
8

Giả sử tôi muốn đặt tất cả các số là phiên bản Monoid. Thay vì phải tạo một phiên bản cho mỗi Num như sau:Bạn có thể tạo một thể hiện của một lớp không phải cho một loại mà cho cả một lớp trong Haskell không?

instance Monoid Int where 
    mappend = (+) 
    mempty = 0 

instance Monoid Float where 
    mappend = (+) 
    mempty = 0.0 

-- etc 

Có điều gì tương tự không?

instance Num t => Monoid t where 
    mappend = (+) 
    mempty = 0 

Sửa

Một số đang trả lời với phần mở rộng GHC và cảnh báo về các vấn đề tiềm năng; Tôi thấy rằng thông tin, nhưng tôi nghĩ rằng tôi sẽ dính với Sum, Product và bất cứ điều gì coerce nào.

+6

những gì bạn đang tìm kiếm đã có sẵn - nhưng có nhiều hơn một Monoids có thể cho số - đó là lý do tại sao nó có 'Sum' và' Product' ([xem Data.Monoid] (https: //hackage.haskell) .org/package/base-4.8.1.0/docs/Data-Monoid.html # t: Monoid)) – Carsten

+1

@Carsten Vì vậy, bây giờ tôi biết về 'Sum', tôi có thể làm điều này:' mconcat ([1,2] :: Sum Int) ', là tốt đẹp, nhưng tôi không thể làm' mconcat ([1,2] :: Sum Float) ', cũng không' mconcat ([1,2] :: Sum Fractional) '. Cách thích hợp để sử dụng 'Sum' cho' Float 'và' Double 'là gì? –

+0

Tôi không biết đầu tiên bạn làm việc đầu tiên như thế nào - nhưng 'mconcat ([1,2] :: [Sum Float])' hoạt động tốt cho tôi;) – Carsten

Trả lời

21

Tôi giải thích điều này khi hỏi về một tiền đề chung, thay vì cụ thể về MonoidNum.

Có thể bạn có thể nhận được những gì bạn đã viết để hoạt động, bằng cách bật tiện ích mở rộng ngôn ngữ FlexibleInstances, UndecidableInstances và sử dụng các phiên bản chồng chéo.

Nhưng có lẽ bạn sẽ không muốn: nó có vẻ nhưinstance Num t => Monoid t where ... đang nói

"Nếu t là một thể hiện của Num, dưới đây là cách để làm cho t một thể hiện của Monoid ..."

Thật không may, điều đó không đúng. Những gì nó thực sự nói là giống như

"Dưới đây là cách thực hiện t một thể hiện của Monoid. Đầu tiên, nó là cần thiết rằng t là một thể hiện của Num. Tiếp theo ..."

Vì vậy, nếu bạn viết một tuyên bố dụ như thế này, bạn không thể viết bất kỳ khai báo cá thể nào khác. (Ít nhất không phải không có OverlappingInstances, trong đó sẽ đưa vấn đề riêng của mình.)

6

GHC cho phép định nghĩa của bạn với một số phần mở rộng ngôn ngữ cho phép

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 

instance Num t => Monoid t where 
    mappend = (+) 
    mempty = 0 

Điều này làm cho 2 <> 3 kết quả trong 5.

Nhưng này trùng lặp với Monoid trường hợp khác, vì vậy cố gắng để đánh giá kết quả "Hello" <> "World" với một lỗi: Overlapping instances for Monoid [Char]

Vì vậy, tôi nghĩ rằng câu trả lời ngắn gọn là: không có.

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