haskell中的類型類是相當於面向對象語言的介面嗎?

小弟正在看haskell趣學指南(只是作為拓寬眼界吧),看見「千萬不要將haskell的類型類與面向對象語言中類(Class)的概念混淆」,然後有種細思極恐的感覺,然後就掉進這個圈子裡出不來了。

然後看見後面Eq類型類/Ord類型類,==、/=、&<、&>都是類型類的「實例」,那麼類型類是相當於面向對象語言的介面嗎?


非常勉強。因為OOP語言沒有kind系統,interface僅相當於Haskell里kind為*的class。


請看 @閱千人而惜知己的演講函數式編程杭州分享會20150718-張淞,其中有講到Haskell的類型類。

類型類可以看成類型的約束,也可以大致的看成類似Java中的介面,但這兩者是不同的東西。Haskell的類型類可以有些預設的函數實現,有函數之間的關係聲明,有函數應用的規則聲明。另外類型類可以很方便的多繼承。


Haskell 裡面,一元、作用域 * 的類

print :: (Show a) =&> a -&> IO()

大致等同於 C# 的

IOTask print&(T x) where T : Show { ... }

而和 C# 裡面用 interface 的做法相似的得開 Haskell 的 Existential quantifier 擴展,用 Existential type。


可以類比,但是haskell的type class是靜態的,C#的interface是動態的。


只能說類似,具體有什麼區別。。。你只有用了才知道,反正我不會解釋。

typeclass 約束的 instance 是 type,interface 約束的是 value

另外,反正我不知道怎麼用interface實現這種東西。。。

fuck :: forall a b. (Class a, Class b) =&> a -&> b

( ̄▽ ̄)

還有這玩意徹底沒有類比了 https://wiki.haskell.org/Multi-parameter_type_class


和c++ 的模板的感念更接近

每個模板都可以有默認的實現,也可以給不同的類型進行特化,


類比是有用的,但是可能讓你誤入歧途。

想要理解這些問題,需要抽象,俗稱上層次。

最基本的是代數類型的值,亦即各種字面值,如123,「hello world」等。這是最基本的程序磚塊。

如何操作這些值,我們有些想法。比如123可以看作是自然數,自然可以把針對自然數的操作施用其上。這裡引申出了自然數這個概念。有了概念,我們可以澄清一些專門針對自然數的操作,加減乘除什麼的,這裡我們引入了類的概念。類是一類值的公共操作的集合。基礎類的行為由程序語言定義,而擴展類則由程序員定義。

不同的類可以有相同的操作,比如序列化計算機內部表達為人類可讀的表達以及反序列人類可讀的表達為機器內部表達。這些操作有一致或者類似的結構。抽象出來就是類型類。類型類是一類類的公共操作的結合。這裡還有另外一種操作,那就是針對類本身的操作,比如類提升為類的序列,類的引用。這個不是類型類要考慮的事情。

回到問題。你的理解沒錯,但是要注意各種語言的實現限制。


https://wiki.haskell.org/OOP_vs_type_classes


推薦閱讀:

Lambda calculus引論(目錄)
愉♂悅的scheme之旅(6)-用宏構建DSL
如何編譯函數閉包
Stackage 鏡像使用說明

TAG:函數式編程 | Haskell |