如果我有一個我知道有歧義型別的運算式,有沒有辦法讓 GHCi 實際上完整地告訴我那個型別,這樣我就可以看到自己的確切歧義,而不必將它從零碎的部分拼湊起來錯誤資訊?例子:
GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help
ghci> default ()
ghci> :t v show . read
<interactive>:1:1: error:
? Ambiguous type variable ‘b0’ arising from a use of ‘show’
prevents the constraint ‘(Show b0)’ from being solved.
Probable fix: use a type annotation to specify what ‘b0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 23 others
...plus 21 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
? In the first argument of ‘(.)’, namely ‘show’
In the expression: show . read
In the expression: show . read
<interactive>:1:8: error:
? Ambiguous type variable ‘b0’ arising from a use of ‘read’
prevents the constraint ‘(Read b0)’ from being solved.
Probable fix: use a type annotation to specify what ‘b0’ should be.
These potential instances exist:
instance Read Ordering -- Defined in ‘GHC.Read’
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
instance Read Integer -- Defined in ‘GHC.Read’
...plus 23 others
...plus 10 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
? In the second argument of ‘(.)’, namely ‘read’
In the expression: show . read
In the expression: show . read
ghci>
在那個例子中,我想要的是 GHCi 告訴我show . read :: (Show a, Read a) => String -> String或類似的東西。
uj5u.com熱心網友回復:
你不會讓 ghci 告訴你這種模棱兩可的型別,但別擔心。這個show . read例子相當人為,你不會在實踐中遇到它。你至少可以從中做出一個定義
readShow :: forall a. Read a => Show a => String -> String
readShow = show @a . read @a
uj5u.com熱心網友回復:
GHCi 為您提供您想要的資訊,但不是您想要的格式。
隨著-fdefer-type-errors你得到show . read :: String -> String錯誤后。你很失望,它不是像show . read :: (Read a, Show a) => String -> String.
問題是它不明確的全部原因是型別變數a 沒有出現在整個運算式的型別中,以便附加約束。約束必須在運算式“內部”解決,與整體型別無關String -> String。
GHC當然可以在型別中添加一個虛假的型別變數,并說show . read :: (Read a, Show a) => String -> String只是為了告訴你不明確的型別。但它已經告訴你關于模棱兩可的型別,如果你真的閱讀了錯誤訊息,它會告訴你:
? Ambiguous type variable ‘a0’ arising from a use of ‘show’
prevents the constraint ‘(Show a0)’ from being solved.
究竟是什么問題
Probable fix: use a type annotation to specify what ‘a0’ should be.
要修復它,您可能需要添加更多型別資訊
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 21 instances involving out-of-scope type
一個“潛在”實體串列,告訴您可以在它建議您可能需要的附加型別資訊中使用哪些型別(誠然,這在這里不是很有用)。
? In the first argument of ‘(.)’, namely ‘show’
In the expression: show . read
究竟哪里的問題; 查明確切的子運算式(因為可以想象show在同一行上可能有不止一種用法)。
show是代碼中需要Show實體的確切點,并且對于應該使用什么型別來查找實體存在歧義。不是呼叫的回傳型別.,這是明確的String -> String。這就是 GHC 告訴您的(對于Read下一條錯誤訊息中的約束也類似)。
考慮這個例子:
ghci> :t length [1] 10
length [1] 10 :: Int
在正常的默認規則下,這很好。隨著default ()你得到一個模棱兩可的錯誤型別有關無法解決約束Num a0。但是看到以下型別有用嗎?
length [1] 10 :: (Num a) => Int
我怎么知道哪里有歧義?是1還是10,或者length可能需要一個Num約束(它可以寫成這樣genericLength)?GHC 實際上告訴你的是1:
? Ambiguous type variable ‘a0’ arising from the literal ‘1’
prevents the constraint ‘(Num a0)’ from being solved
這比您想要的資訊更豐富。
You say you want to "see the exact ambiguity for myself, instead of having to piece it together from bits of the error messages", but that's actually not what you're asking for. GHC is telling you the exact ambiguity (both the constraint that can't be solved and where it needs to be solved). What you are asking for is to see a type signature with variables in the constraints that don't appear on the right hand side of the =>, so that you can infer what must have gone wrong in the internals to cause that instead of reading the error message where it tells you what went wrong in the internals to cause that.
大概你想要那個,因為它會更短更容易讓你識別,我當然可以理解!我認為處理該問題的正確方法只是學習 GHC 的錯誤訊息,直到您可以Ambiguous type variable ‘a0’ arising from a use of ‘read’ prevents the constraint ‘(Read a0)’ from being solved.盡可能輕松地“模式匹配” (Read a, Show a) => String -> String。
1實際上的回傳型別length是明確地Int,它設定了Num通過用于約束 和10到Int,所以總體表達明確地鍵入Int。歧義僅在于1串列內部的型別,而不在于 的回傳型別 ,因此結果中不應存在Num約束。
uj5u.com熱心網友回復:
我認為您無法讓 GHCI 告訴您。我認為這是因為即使您打開 AllowAmbiguoustypes 以便運算式編譯,GHCI 的默認規則將可讀型別決議為(),而不是型別引數。沒有比String -> String. 并且讓它多型是沒有意義的,因為這個函式的客戶端不可能放置一個型別注釋來指示他們想要讀取的型別。
與 相比read . show,GHCI 很樂意為您提供型別,因為它可以根據給定的引數推斷要使用的型別。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/316807.html
