Haskell 的 Typeclass 怎麼理解?
中文對應哪個關鍵詞?
然後怎麼理解這段英文介紹,我感覺不好懂(Java 不懂的情況下)。A typeclass is a sort of interface that defines some behavior. If a type is a part of a typeclass, that means that it supports and implements the behavior the typeclass describes. A lot of people coming from OOP get confused by typeclasses because they think they are like classes in object oriented languages.Well, theyre not. You can think of them kind of as Java interfaces, only better.
如果從工程的角度來看,Haskell的type class解決了以下幾類問題1、類型推導如何兼容重載函數2、定義OO語言所缺失的concept /*mapping*/(如C#的IComparable&
補充一下其他答案里好像漏掉的一點:type class其實更嚴謹的說法叫constructor class。。以下答案中「type class」均指代constructor class。
以最簡單的show函數為例,show :: Show a =&> a -&> String,只要某個值type是Show類的instance,就可以調用show函數。另外一個例子是fmap :: Functor f =&> (a -&> b) -&> f a -&> f b。注意到了什麼?f是Functor類的instance,但是f並不是一個類型;f a和f b才是類型。換句話說,能夠成為某個類的instance的東西,並不一定是type,還有可能是type constructor。。
如果把type看成另一種value的話,那麼type constructor其實不過就是type function而已。。然後,比如a -&> b就可以表述為(-&>) a b,而這個(-&>)就是一個type function,而type function也支持自動的currying。
怎樣區分一個東西是type和type function?你需要一個叫做kind的概念。。規定Int,Bool之類的類型的kind為*,然後像Functor/Monad等類的成員的kind為* -&> *,而(-&>)的kind為* -&> * -&> *。。然後kind為*的constructor才能夠描述值類型,而其他kind的東西都可以看成type function。。然後,定義一個type class的時候,他的instance可以是一個具體的type(也就是說kind為*),也可以是其他kind的constructor。。
然後在實現編譯器的時候,type inference之前還有一步簡單的kind inference。。確保不會出現type X = Int Int之類的kind錯誤。
更強的拓展,dependent type什麼的,還沒學就不提了。。
ref:A system of constructor classes: overloading and implicit higher-order polymorphismhttps://www.haskell.org/onlinereport/haskell2010/Demystifying Type Classes
Haskell的Typeclass從範疇論來看就是一個範疇中的態射(morphism),而type就是範疇中的對象(collection),instance一個Typeclass後就得到一個範疇(category)。比如簡單的Eq這個Typeclass,其定義如下:
class Eq a where
(==), (/=) :: a -&> a -&> Bool
x == y = not (x /= y)
x /= y = not (x == y)
instance Eq Int where
(==) = eqInt
這樣,我們就得到了一個基於包含Int和Bool這兩個type的對象集(collection)和以Eq為態射(morphism)的範疇。
」class of types」,可以理解為對某一系列類型的抽象(即高階類型)
它表示某種抽象行為,這種行為的具體實現 要由它的具體類型參數決定
在scala里沒有這個關鍵字,typeclass 則成為一種模式,通過泛型來描述某種通用行為,
對每個想要用到這種行為的具體類型,在實現時行為部分並不放在類型自身中,而是通過實現一個type class實例(對泛型具化),最後在調用時(通過隱 式參數)讓編譯器自動尋找行為的實現。
優點
- 抽象分離:參考前面的
- 可組合性:[T: Comparable2]語法 可以指定多個類型如:[T: Comparable2 : Order] 比要求某個抽象介面或者介面組合要靈活的多,並且可以組合不同type class的實現
- 可覆蓋性:可利用隱式系統覆蓋Type class的默認實現
- 類型安全:都在編譯期
對,我就是來安利scala的
-------------------------------------------type classes 是語言對於qualified types 的實現形式,qualified types 則是對polymorphic types加上了predicate限定,使得其處於polymorphic types和monomorphic types之間,功能上實現了parametric polymorphism + overloading。
type classes + type constructors (+ kind system) 的應用被稱為:Constructor classeshttps://www.cs.ox.ac.uk/files/3432/PRG106.pdf
http://people.csail.mit.edu/dnj/teaching/6898/papers/wadler88.pdfhttp://www.cs.tufts.edu/~nr/cs257/archive/mark-jones/fpca93.pdf簡單來說就是可以實現給靜態類型語言的 polymorphism 加上 constraints。
而且 typeclass 的用法遠不止於此,一種玩法是實現 type function,見:https://www.haskell.org/haskellwiki/GADTs_for_dummies中文應該叫做類型類,實際上在OO語言里是找不到類似的概念的。類型類定義了一組函數,但是並沒有實現,因此說是一個interface,如果一個類型要支持一個類型類,就要使用instance來定義,也就是給你的類型實現這個類型類指定的介面。
比如,我定義一個類型:data Demo = Demo1 String| Demo2 Int一個基本的需求就是我想列印出這個類型的數據,這有一個標準的類型類,Show, 其定義為:class Show m where
show :: a -&> String為了讓Demo類型的數據也能使用show函數,我們就要實現它:
instance Show Demo whereshow (Demo1 str) = strshow (Demo2 num) = show num於是,當我們有一個Demo類型的數據,比如d時,可以這樣:show dBounded quantification
我不知道問問題的同學有什麼語言的基礎,不好舉例子啊
這個東西說起來確實類似java里的介面。定義了一種規格
比如Eq表示可判等的一類事物,具有==和/=方法比如Ord表示有序(可比較)的一類事物,具有&>,&<,&>=,&<=等方法而一個具體類型,比如Int,它既是Eq的實例,也是Ord的實例,也就是說Int是可判等,可比較的,因此Int具有以上所有這些方法還是一個初學者對typeclass的理解:typeclass確實最像Java中的Interface,但比它更靈活。因為
- 你可以動態的為一個Type實例化某個typeclass,而Java中Class的定義只能到Class相關的代碼中去修改,並且Class繼承哪些介面也是固定的。從這個意義上來說,typeclass有點像Python中的修飾。
- 甚至,在不同的模塊中,對同一個Type實例化同一個typeclass可以有不同的實現,只要不導出產生衝突即可。我專門測試了一下,結果可以邏輯顛倒:
--ClassDefine.hs
module ClassDefine (BasicEq(..)) where
class BasicEq a where
isEqual :: a -&> a -&> Bool
-- ModuleA.hs
module ModuleA (demoA) where
import ClassDefine(BasicEq(..))
instance BasicEq Bool where
isEqual True True = True
isEqual False False = True
isEqual _ _ = False
demoA :: Bool -&> Bool -&> Bool
demoA = isEqual
--ModuleB.hs
module ModuleB (demoB) where
import ClassDefine(BasicEq(..))
instance BasicEq Bool where
isEqual True True = False
isEqual False False = False
isEqual _ _ = True
demoB :: Bool -&> Bool -&> Bool
demoB = isEqual
-- TestTypeClass.hs
import ModuleA(demoA)
import ModuleB(demoB)
覺得像C++中的concept.
[1] Stackoverflow: How are c++ concepts different to Haskell typeclasses?[2] OOP vs type classes[3] Generic programming with C++ concepts and
Haskell type classes—a comparison, http://publications.lib.chalmers.se/records/fulltext/local_124669.pdf
typeclass從某種方面看,和java的interface有點像。規定了一個類型必須具有什麼樣的操作。這樣某些函數可以只要求某個類型具有某種介面而不是要求需要某個名字,從而達到了所謂的范性。比如,排序,只需要知道類型比較大小的方法就可以了,haskell中就是Ord,這樣所有Ord的instance,都可以應用排序函數(你自己定義的任何類型實現了這個typeclass也可以)。
named overloading
對象中的類 結構類 描述對象的結構共性typeclass 行為類 描述實例的行為共性
我理解的 Typeclass 是用來構造一個具體類型的初始模型,這個模型上定義了一系列行為函數,這些函數在 Typeclass 中不一定有具體的實現,但一定有類型聲明。
當某個具體的類型通過 instance 關鍵字變成這個 Typeclass 的實例時,這個具體的類型就獲得了 Typeclass 這個初始模型上定義的一系列行為函數,當然這個具體的類型也可以根據行為函數的類型聲明給出自己的一套實現方式,這樣就達到了重載的效果。
前面的回答也提到了,Typeclass 其實就是一系列行為的抽象。
推薦閱讀:
※為什麼haskell里需要monoid?
※為什麼 Haskell 始終沒法流行呢?
※Robert Harper 不支持Haskell 的理由是?
TAG:Haskell |