class Foo a where
(++=) :: a -> a -> a
cool :: (a -> b -> b) -> a -> b
,並希望使
class Bar a where
(++=) :: (a -> b) -> a -> b
magic :: a -> b
其中有重疊的方法名稱,(++=)
。有什麼辦法可以做到這一點?
class Foo a where
(++=) :: a -> a -> a
cool :: (a -> b -> b) -> a -> b
,並希望使
class Bar a where
(++=) :: (a -> b) -> a -> b
magic :: a -> b
其中有重疊的方法名稱,(++=)
。有什麼辦法可以做到這一點?
這個問題有一個微妙的「沒有,但肯定」這樣回答的,這需要進入三個概念:
第1點:Haskell中的每個定義都有一個簡短的非限定名稱,如map
,以及一個長的限定名稱,如Data.List.map
。
第2點:當您將模塊導入到另一個模塊時,可以執行合格導入或非限定導入。當您使用不合格的導入時,您帶入的外國模塊的名稱將以其短名稱進行別名。當你做一個合格的進口,他們將只提供下修改後的名稱:
import qualified Data.Map as Map
現在模塊這個地方出現了,該Data.Map.map
功能是別名Data.map
下可見。第三點:這意味着每個Haskell定義都有一個完全限定的名稱,由它的短名稱和定義它的模塊確定,但是在每個導入的模塊中也有非限定或部分限定的別名。現在
,你的問題有兩個答案:
Foo
和Bar
類,那將會失敗。在你的例子中,你的意思是'地圖.map'或'將限定的Data.Map導入爲Data',對嗎? – suffi
不,你不能,至少在同一模塊內。您可以在兩個不同的模塊中聲明class Foo
和class Bar
並將它們中的每一個導入到相同的文件中,但您仍然必須至少使用qualify
以避免衝突。
所以它是「是的,你可以,如果...」而不是「你不cannotl :) –
@ErikAllik他們從字面上不能有相同的名字,合格會導致他們有不同的名字 –
下編譯沒有任何錯誤:
主。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
不知道哪一個被引用,如果我們使用了不合格的導入。因此,如果我們只想定義類實例,那麼我們不需要限定的導入。
在OOP中,同名方法是允許的,因爲'this'對象的類型可以消除它們之間的歧義。在Haskell中,沒有'this':'Foo a'的方法不會隱式地採用'a'的參數。即使他們這樣做了,類型推斷也會變得相當複雜,因爲你需要計算'this'的類型_before_你可以知道方法的類型。在大多數OOP語言中,沒有或只有很少的類型推斷w.r.t.功能語言,所以這不是一個問題。 – chi
此外,這些函數不是方法,更確切地說。 –
@Erik Alik:實際上,儘管與OO概念有很大的不同,['method'一詞在技術上是正確的](https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3) 。 –