代碼什麼是AllowAmbiguousTypes,爲什麼在這個「全部」例子中需要?
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
-- I know this particular example is silly.
-- But that's not the point here.
g :: forall a . RealFloat a => Bool
g = True
main :: IO()
main = print (g @Double)
未能在GHC 8.0編譯錯誤
• Could not deduce (RealFloat a0)
from the context: RealFloat a
bound by the type signature for:
g :: RealFloat a => Bool
at app/Main.hs:3:6-35
The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘g’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature:
g :: forall a. RealFloat a => Bool
因此增加AllowAmbiguousTypes
將使代碼編譯。
這裏是我的問題:
- 到底是什麼
AllowAmbiguousTypes
? - 爲什麼需要使這個特定的代碼工作?
- 我擔心加入
AllowAmbiguousTypes
在這個特定的代碼中給了我比我真正想要的更多的東西。聽起來很可怕。這聽起來似乎會讓Haskell的類型系統不太安全,也許在與此特定代碼無關的其他領域。這些恐懼是否沒有根據? - 有沒有其他的選擇?在這種情況下,Haskell好像插入了一個我從來沒有要求的類型變量。是否沒有擴展來告訴Haskell不要創建這些無關的類型變量 - 並且只使用那些我明確告訴它用我自己的明確的
forall a
添加的變量? - 添加了一個問題,因爲user2407038的評論:你會說
AllowAmbiguousTypes
是一個用詞不當嗎?它會更好地命名爲AllowUnusedTypeVariables
?
不明確的類型是在其上下文中有一個類型變量的類型,在該類型的正文(在該類型的右側)沒有提及。所以''RealFloat a => ..'在'..'沒有提到'a'時是不明確的。模糊的類型通常是程序員錯誤,在TypeApplications之前它們完全沒用,所以你需要一個擴展來允許它們。對於最後兩個問題:它不會以任何方式使typechecker'不安全';你的選擇是寫'RealFloat a => Proxy a - > Bool',其中[Proxy](https://hackage.haskell.org/package/base-4.9.1.0/docs/Data-Proxy.html)是這裏。 – user2407038
作爲替代方案,您可以使用'RealFloat a =>標記Bool',其中'Tagged'來自'tagged'包,在某些情況下,這可能比代理方式更有效。 – dfeuer
在我眼裏,'AllowAmbiguousTypes'是無害的。在許多lambda結石中,類型總是顯式傳遞(例如'map @a @b f xs')。在普通的Haskell中,類型是推斷的 - 意味着我們不必傳遞它們(好),即使我們想要(壞),我們也不能傳遞它們。因此,必須禁止不能從參數類型或返回值推斷出的tyvars類型。因此,我們必須使用代理/標籤只是爲了讓它們可以推測,增加混亂。但是,現在GHC允許顯式類型的應用程序,所以我們不再需要這樣做。 – chi