Có thiên vị, nhưng tôi nghĩ đây là cơ hội tuyệt vời để sử dụng Control.Newtype, một phần nhỏ của bộ đó chỉ là "cabal install newtype".
Đây là giao dịch. Bạn muốn lật xung quanh các nhà xây dựng loại để có được bàn tay của bạn trên functoriality (ví dụ) trong một tham số khác nhau. Xác định một Newtype
newtype Flip f x y = Flip (f y x)
và thêm nó vào lớp Newtype
do đó
instance Newtype (Flip f x y) (f y x) where
pack = Flip
unpack (Flip z) = z
Lớp Newtype
chỉ là một newtypes sắp xếp thư mục để tương đương mảy may của họ, cung cấp bộ tiện dụng, ví dụ op Flip
là nghịch đảo của Flip
: bạn không cần nhớ những gì bạn gọi nó.
Đối với các vấn đề trong câu hỏi, bây giờ chúng ta có thể làm những thứ như thế này:
data Bif x y = BNil | BCons x y (Bif x y) deriving Show
Đó là một kiểu dữ liệu hai tham số đó sẽ xảy ra là functorial trong cả hai tham số. (Có lẽ, chúng ta nên làm cho nó một thể hiện của một lớp Bifunctor, nhưng dù sao ...) Chúng ta có thể làm cho nó một Functor
hai lần trở lên: một lần cho các tham số cuối cùng ...
instance Functor (Bif x) where
fmap f BNil = BNil
fmap f (BCons x y b) = BCons x (f y) (fmap f b)
... và một lần cho là người đầu tiên:
instance Functor (Flip Bif y) where
fmap f (Flip BNil) = Flip BNil
fmap f (Flip (BCons x y b)) = Flip (BCons (f x) y (under Flip (fmap f) b))
nơi under p f
là một cách gọn gàng để nói op p . f . p
.
Tôi cho bạn biết không có lời nói dối: chúng ta hãy thử.
someBif :: Bif Int Char
someBif = BCons 1 'a' (BCons 2 'b' (BCons 3 'c' BNil))
và sau đó chúng tôi nhận
*Flip> fmap succ someBif
BCons 1 'b' (BCons 2 'c' (BCons 3 'd' BNil))
*Flip> under Flip (fmap succ) someBif
BCons 2 'a' (BCons 3 'b' (BCons 4 'c' BNil))
Trong những trường hợp này, có thực sự rất nhiều cách điều tương tự có thể được xem như một Functor
, vì vậy nó là đúng rằng chúng ta phải thực hiện một số tiếng ồn nói mà theo cách của chúng tôi. Nhưng tiếng ồn không phải là tất cả những gì nhiều nếu bạn có hệ thống về nó.
kiểu mới rất tuyệt. Đó là một trong những gói mà, khi tôi lần đầu tiên nhìn thấy nó, tôi muốn tôi được sử dụng nó trong tất cả các công việc trước đây của tôi. –
Trong khi điều này là mát mẻ và hoạt động, nó không thực sự trả lời câu hỏi vì bạn vẫn không thể tạo một thể hiện của Functor cho SomeType2 trực tiếp (và chỉ sử dụng fmap mà không có hàm 'under' wrapper). – ivanm
Câu trả lời cho câu hỏi ban đầu là "không". Hoặc ít nhất, không phải trong Haskell. Ở một mức độ nào đó, nó sẽ là đặc biệt để trình bày một cách giải quyết có câu trả lời là "có". – pigworker