尋找的ConstrainedMonoid
我來到了一個非常類似的問題最近,我終於解決了這個帖子的末尾描述的方式(不涉及獨異,但使用的類型的謂詞)。但是,我接受了挑戰,並試圖編寫一個ConstrainedMonoid
課程。
這裏的想法:
class ConstrainedMonoid m where
type Compatible m (t1 :: k) (t2 :: k) :: Constraint
type TAppend m (t1 :: k) (t2 :: k) :: k
type TZero m :: k
memptyC :: m (TZero m)
mappendC :: (Compatible m t t') => m t -> m t' -> m (TAppend m t t')
好了,還有的小例子,這實際上不添加任何新的東西(我換R
S型參數):
data K = T0 | T1 | T2 | T3 | T4
data R a (t :: K) = R String (Maybe (String -> a))
instance ConstrainedMonoid (R a) where
type Compatible (R a) T1 T1 =()
type Compatible (R a) T2 T2 =()
type Compatible (R a) T3 T3 =()
type Compatible (R a) T4 T4 =()
type Compatible (R a) T0 y =()
type Compatible (R a) x T0 =()
type TAppend (R a) T0 y = y
type TAppend (R a) x T0 = x
type TAppend (R a) T1 T1 = T1
type TAppend (R a) T2 T2 = T2
type TAppend (R a) T3 T3 = T3
type TAppend (R a) T4 T4 = T4
type TZero (R a) = T0
memptyC = R "" Nothing
R s f `mappendC` R t g = R (s ++ t) (g `mplus` f)
這種不幸發生很多冗餘類型實例(OverlappingInstances
似乎不適用於類型族),但我認爲它在類型級別和值級別上滿足幺半羣法則。
但是,它並沒有關閉。它更像是一組不同的monoid,索引K
。如果這就是你想要的,那就夠了。
如果您想了解更多
讓我們來看看不同的變體:
data B (t :: K) = B String deriving Show
instance ConstrainedMonoid B where
type Compatible B T1 T1 =()
type Compatible B T2 T2 =()
type Compatible B T3 T3 =()
type Compatible B T4 T4 =()
type TAppend B x y = T1
type TZero B = T3
memptyC = B ""
(B x) `mappendC` (B y) = B (x ++ y)
這可能是這是有道理的在您的域名的情況下 - 但是,它不是一個獨異了。如果您嘗試製作其中一個,它將與上述實例相同,只是使用不同的TZero
。我其實只是在這裏猜測,但我的直覺告訴我,唯一有效的幺半羣實例就像R a
;只有不同的單位值。否則,你會最終得到一些不必要的聯想(可能與終端對象,我認爲),這是而不是在組合下關閉。如果你想限制組成等於K
s,你將失去單位價值。
一個更好的辦法(恕我直言)
以下是我真正解決我的問題(我根本就沒想到類羣的當年,因爲他們沒有任何意義,無論如何)。該解決方案主要剝掉以外的所有Compatible
「約束製片人」,這是留給作謂語兩類:使用像
foo :: (Matching a b) => B a -> B b -> B Int
type family Matching (t1 :: K) (t2 :: K) :: Constraint
type instance Matching T1 T1 =()
type instance Matching T2 T1 =()
type instance Matching T1 T2 =()
type instance Matching T4 T4 =()
這使您完全控制您的兼容性的定義,以及你想要什麼類型的作品(不一定是monoidal),而且更一般。它可以擴展到無限種,太:
-- pseudo code, but you get what I mean
type instance NatMatching m n = (IsEven m, m > n)
回答你的最後兩點:
難道這是更容易?
什麼其實我希望能夠寫出如下:
type family Matching (t1 :: K) (t2 :: K) :: Constraint
type instance Matching T1 y =()
type instance Matching x T1 =()
type instance Matching x y = (x ~ y)
我擔心這有嚴重的理由不被允許的;然而,也許,它只是沒有實施...
編輯:現在,我們有closed type families,正是這樣做。
你能更好地解釋什麼樣的組合有意義,什麼不可以?爲什麼有30個? (順便說一句,你可以寫'R s f \'mappend \'R t g = R(s ++ t)(g \'mplus \'f)')。 –
類型級別的整數可以嗎?數據R(t∷Int)a = R String(Maybe(String→a))'。 ' – dave4420