有沒有辦法進一步約束現有類型的上下文?Howto進一步約束Haskell中的現有類型
例如,類型類Functor
:
class Functor f where
fmap :: (a -> b) -> f a -> f b
這個類定義並不強制a
或b
是的Show
的元件。此類型類也是我自己包含的類,所以我不能影響類定義。是否仍然有可能,以後只允許a
和b
的成員Show
?
有沒有辦法進一步約束現有類型的上下文?Howto進一步約束Haskell中的現有類型
例如,類型類Functor
:
class Functor f where
fmap :: (a -> b) -> f a -> f b
這個類定義並不強制a
或b
是的Show
的元件。此類型類也是我自己包含的類,所以我不能影響類定義。是否仍然有可能,以後只允許a
和b
的成員Show
?
不直接。無需更改源代碼並重新編譯,就無法更改類的定義。在標準庫中定義類的情況下,這會導致代碼的大量中斷,所以不是一個現實的選擇。
但是,可以包裹類,並添加所需的約束,
class Functor f => ShowFunctor f where
smap :: (Show a, Show b) => (a -> b) -> f a -> f b
smap f = fmap f
,然後使用類,而不是原來的。
但也許你並不需要額外的類併爲您的應用,只需要在頂層定義smap
,簡單地用這個來代替fmap
,
smap :: (Functor f, Show a, Show b) => (a -> b) -> f a -> f b
smap = fmap
可能'ShowFunctor'不應該是'Functor'的子類,因爲它正在添加一個前提條件。每個「Functor」都是「ShowFunctor」,但不一定相反。 – 2012-03-07 10:52:48
我猜想,但很高興知道肯定... thx – frosch03 2012-03-07 11:02:41
如果重點是進一步限制現有的類,我認爲使它成爲一個子類是正確的方法。除非我完全誤解了,並且OP希望'ShowFunctor'的實例只能包裝屬於'Show'('ShowList = ShowList :: ShowList = Show [a] - > ShowList a;實例ShowFunctor ShowList的類型,其中smap f (ShowList xs)= ShowList(fmap f xs)'),但這不能由類強制執行(至少不在H2010中)。 – 2012-03-07 11:03:01
你不能做,沒有破事(目前)。
你有幾個選項
Functor
類其實我們現在知道如何讓實例去廣告d約束,所以也許有一天這不會太糟糕,參見Subcategories in Haskell來處理幾乎完全是這個問題的論文。在該文件的語法比現在什麼工作在GHC有一點不同,但基本上我們希望重新定義Functor
類看起來像
class Functor f where
type SubCat f :: * -> Constraint -- associated constraint
type SubCat f =() -- default definition
fmap :: (SubCat f a, SubCat f b) => (a -> b) -> f a -> f b
這將是很有趣的聽到你爲什麼要擁有人爲約束代碼並不合理。可能會有誤解可以解決。 – Ingo 2012-03-07 11:05:29
約束通常放在函數上,而不是數據/類型類。原因是:你永遠不會知道你需要什麼。假設你使用Daniel答案中的'ShowFunctor'。你不能使它成爲一個應用程序(因此也是一個Monad),因爲應用程序需要能夠包裝功能,並且功能沒有顯示實例。 – mb14 2015-06-07 06:51:36