2012-03-07 48 views
4

有沒有辦法進一步約束現有類型的上下文?Howto進一步約束Haskell中的現有類型

例如,類型類Functor

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

這個類定義並不強制ab是的Show的元件。此類型類也是我自己包含的類,所以我不能影響類定義。是否仍然有可能,以後只允許ab的成員Show

+0

這將是很有趣的聽到你爲什麼要擁有人爲約束代碼並不合理。可能會有誤解可以解決。 – Ingo 2012-03-07 11:05:29

+0

約束通常放在函數上,而不是數據/類型類。原因是:你永遠不會知道你需要什麼。假設你使用Daniel答案中的'ShowFunctor'。你不能使它成爲一個應用程序(因此也是一個Monad),因爲應用程序需要能夠包裝功能,並且功能沒有顯示實例。 – mb14 2015-06-07 06:51:36

回答

10

不直接。無需更改源代碼並重新編譯,就無法更改類的定義。在標準庫中定義類的情況下,這會導致代碼的大量中斷,所以不是一個現實的選擇。

但是,可以包裹類,並添加所需的約束,

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 
+0

可能'ShowFunctor'不應該是'Functor'的子類,因爲它正在添加一個前提條件。每個「Functor」都是「ShowFunctor」,但不一定相反。 – 2012-03-07 10:52:48

+0

我猜想,但很高興知道肯定... thx – frosch03 2012-03-07 11:02:41

+0

如果重點是進一步限制現有的類,我認爲使它成爲一個子類是正確的方法。除非我完全誤解了,並且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

2

你不能做,沒有破事(目前)。

你有幾個選項

  1. 定義自己的限制Functor
  2. 不要擔心定義一個類,只是定義一個函數,你想要做
  3. 使用RMonad package
  4. 什麼作弊

其實我們現在知道如何讓實例去廣告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