Tôi đang làm việc trên một hàm functor có chứa một monoid để "xem" việc thực hiện. Tuy nhiên, đôi khi tôi không quan tâm đến phần này chút nào, vì vậy sự lựa chọn của monoid là không liên quan vì nó sẽ không bao giờ được tiêu thụ. Tôi đã đơn giản hóa những gì tôi có vào:Sử dụng các loại ràng buộc và loại gia đình có hạn chế 'giới hạn'
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a() where render = const()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render
được sử dụng để chuyển đổi khác nhau a
s thành một đơn b
. Merge
là một đơn giản hóa lớn của functor thực tế của tôi, nhưng điểm là nó chứa một loại gia đình/hạn chế và ý định của tôi là xác định chính xác những gì Render
ers a Merge
yêu cầu.
Bây giờ, tôi có thể muốn "chạy" các Merge
, nhưng loại bỏ các quan điểm, mà là giống như một cái gì đó như:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of() -> 5
Nhưng điều này sẽ thất bại vì:
Không thể suy ra
(Renderer a())
phát sinh từ việc sử dụng củamerge
tôi đã chọn ()
như monoid của tôi bởi vì f orall a
, chúng tôi có một phiên bản Render a()
. Vì vậy, nếu có một cách để nói rằng Merge a
chỉ có nghĩa là một bộ sưu tập Render
ràng buộc sau đó điều này sẽ làm việc tốt. Tất nhiên, Merge a
là tổng quát hơn thế - nó có thể thêm các ràng buộc tùy ý, giải thích lỗi biên dịch.
Có cách nào để đạt được những gì tôi muốn mà không cần thay đổi chữ ký của runFoo
?
Liệu 'Renderer' luôn bao gồm chính xác một' Render'? –
@Tinctorius - không, nói chung phụ thuộc vào số lượng các loại riêng biệt trong các trường 'Foo' – ocharles
Có lý do tại sao' Merge' không có 'b' làm tham số không? –