簡體   English   中英

為什么Haskell會解決“過載”運算符問題?

[英]Why has Haskell troubles resolving “overloaded” operators?

這篇文章提出了!!的問題!! 接受的答案告訴我們你正在做的是創造一個新的功能!! 然后你應該避免導入標准的。

但是,如果將新功能應用於不同類型而不是標准功能,為什么要這樣做呢? 編譯器是否能夠根據其參數選擇正確的編譯器? 是否有任何編譯器標志允許這個?

例如,如果*無定義[Float] * Float

為什么編譯器會哭

>  Ambiguous occurrence *
>  It could refer to either `Main.*', defined at Vec.hs:4:1
>                          or `Prelude.*',

對於此代碼:

(*) :: [Float] -> Float -> [Float]
(*) as k = map (\a -> a*k) as  -- here: clearly Float*Float


r = [1.0, 2.0, 3.0] :: [Float]

s = r * 2.0 -- here: clearly [Float] * Float

main = do
     print r
     print s

允許編譯器根據類型選擇正確的函數實現是類型類的目的。 沒有它們是不可能的。

為了證明這種方法的合理性 ,您可以閱讀介紹它們的論文: 如何使ad-hoc多態性不那么特別 [PDF]。

真的,原因是這樣的: 在Haskell中,不一定有明確的關聯“變量x有類型T

Haskell幾乎和動態語言一樣靈活,因為任何類型都可以是類型變量 ,即可以具有多態類型。 但是在動態語言(以及例如OO多態或C ++模板)中,這種類型變量的類型基本上只是附加到代碼中的值變量的額外信息(因此重載運算符可以看到:參數是Int - >執行此操作,是一個String - > do that),在Haskell中,類型變量存在於類型語言的完全獨立的范圍內。 這為您提供了許多優勢,例如,如果沒有這樣的系統,更高級別的多態性幾乎是不可能的。 但是,這也意味着很難推斷應該如何解決重載函數。 如果Haskell允許你只是編寫重載並假設編譯器在解決模糊性方面做了最好的猜測,那么你經常會在意想不到的地方發現奇怪的錯誤消息。 (實際上,即使你沒有 Hindley-Milner類型系統,這也很容易發生重載.C ++因此而臭名昭着。)

相反,Haskell選擇強制重載是明確的。 您必須首先定義一個類型類,然后才能重載方法,雖然這不能完全排除混淆編譯錯誤,但它更容易避免。 此外,它允許您表達具有無法用傳統重載表達的類型分辨率的多態方法,特別是多態結果 (這非常適合編寫非常容易重用的代碼)。

這是一個設計決策,而不是理論上的問題,不在Haskell中包含它。 正如您所說,許多其他語言使用類型以特殊方式消除術語之間的歧義。 但是類型類具有類似的功能,並且還允許對重載的事物進行抽象。 類型導向的名稱解析不會。

然而,已經針對Haskell討論了類型導向的名稱解析的形式(例如,在解析記錄字段選擇器的上下文中)並且由類似於Haskell的一些語言(諸如Agda(用於數據構造器)或Idris(更一般地))支持。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM