2017-12-18 129 views
9

Ví dụ, tôi có một lớp học loại:Trong Haskell, có thể cung cấp triển khai mặc định cho lớp loại đa param được áp dụng một phần không?

class MyClass a b c where 
    fun01 :: a -> b 
    fun02 :: a -> c 

    fun03 :: a -> b -> c ->() 
    fun04 :: a -> WhatEver 

tôi muốn cung cấp một cài đặt mặc định cho tôi, chúng ta hãy gọi nó BaseDataType trong đó xác định việc triển khai của fun03 về nó tự và fun01fun02. Sau đó, tôi muốn có một cái gì đó như thế này:

class MyClass BaseDataType b c where 
    fun03 = fun01 <$> fun02 ... 
    fun04 = fun02 ... 

Và hơn để hoàn thiện dụ lớp học của tôi và tránh tất cả các mã soạn sẵn cho fun03fun04 tôi chỉ cung cấp fun01fun02 như thế này:

instance MyClass BaseDataType Int Char where 
    fun01 = 1 
    fun02 = 'C' 

Có thể một số phần mở rộng ngôn ngữ cho phép loại hành vi này không? Tôi không thể tìm thấy bất cứ điều gì về chủ đề này.

Trả lời

10

Không có phần mở rộng như vậy, nhưng bạn có thể đạt được chức năng này chỉ đơn giản bằng cách chia lớp học của bạn thành hai lớp:

class MyClass1 a b c where 
    fun03 :: a -> b -> c ->() 
    fun04 :: a -> WhatEver 

class MyClass1 a b c => MyClass2 a b c where  
    fun01 :: a -> b 
    fun02 :: a -> c 

Sau đó, trường hợp của bạn sẽ làm việc theo cách bạn muốn:

-- NB: need the MyClass2 constraint if you use `fun01` or `fun02` in the definitions 
-- This requires UndecidableInstances 
instance MyClass2 BaseDataType b c => MyClass1 BaseDataType b c where 
    fun03 = fun01 <$> fun02 ... 
    fun04 = fun02 ... 

instance MyClass2 BaseDataType Int Char where 
    fun01 = 1 
    fun02 = 'C' 

Users của lớp học của bạn không bị ảnh hưởng; họ có thể tiếp tục tiêu thụ MyClass2 nơi họ đã sử dụng MyClass trước đây và nhận được cùng một chức năng chính xác.


Ngoài: định nghĩa ban đầu của MyClassMyClass1MyClass2 thậm chí không biên dịch do một số lỗi loại mơ hồ (c không được đề cập trong các loại fun01, vv) - Tôi cho rằng lớp này là xác định chỉ cho mục đích trình diễn và tôi đã không cố gắng sửa lỗi này.

4

Bạn có thể sử dụng DefaultSignatures như thế này

class MyClass a b c where 
    fun01 :: a -> b 
    fun02 :: a -> c 

    fun03 :: a -> b -> c ->() 
    default fun03 :: (a ~ BaseDataType) => a -> b -> c ->() 
    fun03 = fun01 <$> fun02 ... 

    fun04 :: a -> WhatEver 
    default fun04 :: (a ~ BaseDataType) => a -> WhatEver 
    fun04 = fun02 ... 
+2

+1, nhưng tôi không nghĩ đây là usuable cho OP vì mặc định là _for ALL_ 'trường MyClass', không chỉ cho môi trường 'MyClass BaseDataType' chuyên môn hóa. (Trong các trường hợp khác, việc triển khai mặc định sẽ chỉ cung cấp một lỗi loại tối nghĩa là để chỉ ra rằng một cá thể tùy chỉnh phải được thay thế.) – leftaroundabout

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