2015-09-14 237 views
6

假設我有兩個不同的類型類可以有相同的方法名嗎?

class Foo a where 
    (++=) :: a -> a -> a 
    cool :: (a -> b -> b) -> a -> b 

,並希望使

class Bar a where 
    (++=) :: (a -> b) -> a -> b 
    magic :: a -> b 

其中有重疊的方法名稱,(++=)。有什麼辦法可以做到這一點?

+0

在OOP中,同名方法是允許的,因爲'this'對象的類型可以消除它們之間的歧義。在Haskell中,沒有'this':'Foo a'的方法不會隱式地採用'a'的參數。即使他們這樣做了,類型推斷也會變得相當複雜,因爲你需要計算'this'的類型_before_你可以知道方法的類型。在大多數OOP語言中,沒有或只有很少的類型推斷w.r.t.功能語言,所以這不是一個問題。 – chi

+2

此外,這些函數不是方法,更確切地說。 –

+4

@Erik Alik:實際上,儘管與OO概念有很大的不同,['method'一詞在技術上是正確的](https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3) 。 –

回答

2

這個問題有一個微妙的「沒有,但肯定」這樣回答的,這需要進入三個概念:

  1. 合格的名稱與不合格的名稱
  2. 模塊和進口
  3. 別名

第1點:Haskell中的每個定義都有一個簡短的非限定名稱,如map,以及一個長的限定名稱,如Data.List.map

第2點:當您將模塊導入到另一個模塊時,可以執行合格導入或非限定導入。當您使用不合格的導入時,您帶入的外國模塊的名稱將以其短名稱進行別名。當你做一個合格的進口,他們將只提供下修改後的名稱:

import qualified Data.Map as Map 

現在模塊這個地方出現了,該Data.Map.map功能是別名Data.map下可見。第三點:這意味着每個Haskell定義都有一個完全限定的名稱,由它的短名稱和定義它的模塊確定,但是在每個導入的模塊中也有非限定或部分限定的別名。現在

,你的問題有兩個答案:

  1. 兩種不同類型的不能具有共享相同完全合格名的方法。所以如果你在同一個模塊中定義FooBar類,那將會失敗。
  2. 兩種不同類型的可以具有共享相同不合格的名稱方法,只要其完全限定名稱是不同的,即,它們在不同的模塊正在定義。但是,要在一個客戶端模塊中使用這兩個客戶端模塊,您至少需要一個限定的導入,以便導入的別名不會發生衝突。
+1

在你的例子中,你的意思是'地圖.map'或'將限定的Data.Map導入爲Data',對嗎? – suffi

4

不,你不能,至少在同一模塊內。您可以在兩個不同的模塊中聲明class Fooclass Bar並將它們中的每一個導入到相同的文件中,但您仍然必須至少使用qualify以避免衝突。

+8

所以它是「是的,你可以,如果...」而不是「你不cannotl :) –

+2

@ErikAllik他們從字面上不能有相同的名字,合格會導致他們有不同的名字 –

0

下編譯沒有任何錯誤:

主。HS:

module Main where 

import qualified Foo 
import Bar 

instance Foo.Foo Char where 
    c1 ++= c2 = c1 

instance Bar Char where 
    f ++= c = f c 

main = do 
    putStrLn $ [ 'a' Foo.++= 'b' ] 

Foo.hs:

module Foo where 

class Foo a where 
    (++=) :: a -> a -> a 

Bar.hs:

module Bar where 

class Bar a where 
    (++=) :: (a -> b) -> a -> b 

所以,換句話說,我們並不需要使用它的完全限定名稱引用++=在實例聲明中,但在main中使用時,我們需要指定我們正在討論的++=。在實例聲明中,我們已經定義了++=的範圍,而main不知道哪一個被引用,如果我們使用了不合格的導入。因此,如果我們只想定義類實例,那麼我們不需要限定的導入。

相關問題