我想為Identity新型別撰寫一個Alternative實體。這個骨架并不難:
instance Alternative Identity where
空 = _
(<|>) = _
然而,對于所有的型別來說,這個實作是不可能的。如果我有一個用于a的Monoid實體,那就很容易了:
instance Alternative Identity where
空 = Identity mempty
(Identity a) <|> (Identity a') = Identity (a < > a')
是否有辦法告訴編譯器,我想只為里面的型別有一個Monoid實體時定義Alternative實體?由于a沒有在任何地方被提及,我不能僅僅使用一個約束條件Monoid a =>。
uj5u.com熱心網友回復:
一個Alternative必須為所有型別a提供empty,沒有任何限制。否則,它就沒有履行Alternative的契約。
也就是說,如果我們有一個實體Alternative f,我們必須有
empty :: forall a . f a
沒有任何進一步的限制。
因此,Identity不是一個Alternative。
這是一個已知的問題,在許多類似的型別類中都可以找到。例如,許多人會喜歡一個Functor Set實體,但這需要
fmap :: (a -> b) -> Set a -> Set b
對于所有型別的a和b,而上面的函式只能在Ord型別上實作。因為我們不能添加約束,所以我們沒有得到一個漏斗。
盡管如此,我們還是可以在Ord型別上實作上述功能。
盡管如此,我們還是可以嘗試使用一個更通用的型別類來說明額外的約束。也許像
這樣的東西class CFunctor c f where
fmap :: (c a, c b) => (a->b) -> f a -> f b
class CFunctor c f => CApplicative c f where
empty :: c a => f a
(<*>) :: (c a, c b, c (a->b)) => f (a->b) -> f a -> f b
但是這些并不是庫中的 "標準 "的。(我猜在 hackage 上應該有類似于上面的約束類變體的東西。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/316967.html
標籤:
