在我看來,型別注釋和型別應用程式在幾個背景關系中扮演著相似的角色。但是在某些情況下,型別應用是不可能的,并且是重現其行為型別注釋的唯一方法
λ> :set -XTypeApplications
λ> :t fromInteger(42::Integer)
fromInteger(42::Integer) :: Num a => a
λ> :t 42
42 :: Num p => p
λ> fromInteger @Float (42::Integer)
42.0
λ> 42 :: Float
42.0
正如這里建議的那樣https://www.reddit.com/r/haskell/comments/ptzzwg/diehls_comments_on_haskell_numbers_confuse/
由于技術原因,我們不能寫 42 @Float。
我的問題是
如果 Type Annotation 和 Type Application 確實是一樣的,結果是一樣的,那么我們寫的時候到底發生了什么
λ> 42 :: Fractional a => a
42.0 -- type defaulting is understood and not the issue of the question
λ> :t it
it :: Fractional a => a
說它相當于
42 @小數a => a
我覺得型別應用很奇怪,如果我的理解是正確的,那么它只適用于具體型別。在我看來,實際上我們是在添加更多約束a而不是應用一個全新的型別。
因此,問題是:這里的幕后實際發生了什么?
因為確實當我手動添加約束時,會發生以下情況(確實是由于層次結構)
λ> 42 :: (Num a, Fractional a) => a
42.0
λ> :t it
it :: Fractional a => a
λ> :t 42 :: (Num a, Fractional a) => a
42 :: (Num a, Fractional a) => a :: Fractional a => a
關鍵是,這種行為感覺更像是我們寫作時實際發生的事情,42 :: Fractional a => a而不是把它想象成42 @Fractional a => a
編輯1
在@leftaroundabout 出色的答案之后,我想為我的問題添加更多背景資訊,以幫助縮小我所追求的范圍。
簡而言之,為什么以下作業有效:
λ> (2 :: (Num p => p)) :: (Fractional p => p)
2.0
但是反過來不行
λ> (2 :: (Fractional p => p)) :: (Num p => p)
<interactive>:5:2: error:
? Could not deduce (Fractional p1)
arising from an expression type signature
from the context: Num p
bound by the inferred type of it :: Num p => p
at <interactive>:5:1-42
or from: Num p1
bound by an expression type signature:
forall p1. Num p1 => p1
at <interactive>:5:31-42
Possible fix:
add (Fractional p1) to the context of
an expression type signature:
forall p1. Num p1 => p1
? In the expression: (2 :: (Fractional p => p)) :: (Num p => p)
In an equation for ‘it’:
it = (2 :: (Fractional p => p)) :: (Num p => p)
我懷疑必須有更多
λ> 42 :: Fractional a => a
等價
it :: ? a . Fractional a => a
it = 42
關鍵是 42 具有派生自 fromInteger(42::Integer) = Num a => a并以某種方式進一步限制它的多型型別是可以Fractional a => a的。反過來是行不通的。
該機制是如何作業的,它是如何命名的,它遵循什么規則?
我最初的理解是型別應用程式正在發生,但顯然基于@@leftaroundabout 答案,我現在明白這不是正在發生的事情。
閱讀周圍我懷疑它與型別統一更相關?
uj5u.com熱心網友回復:
所有多型函式/值都有隱含的額外引數,指定簽名中的型別變數實體化的具體型別。型別應用程式所做的只是將型別值顯式傳遞給該隱式引數,否則型別檢查器將嘗試從背景關系中推斷。
這永遠不會做的是量化新型別變數或對它們應用(非等式)約束。
寫得夠明智的42 @Double。Haskell 恰好不允許這樣做,但很可能是這樣,因為多型文字需要一個隱式型別引數,并且Double是一個合適的實體化。(當然,為什么不直接寫42 :: Double!)特別是,Double有 kind Type,它有一個Num實體。
42 @Fractional然而沒有意義,因為Fractional它是一個型別類,即它有 kind Type -> Constraint,而數字文字不接受類似的東西。當您撰寫42 :: Fractional a => a時,您正在做的是(匿名)定義一個新的多型值。您的 GHCi 請求是定義的簡寫
it :: ? a . Fractional a => a
it = 42
然后你可以寫it @Double或it @Rational(但不是it @Int)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/517130.html
標籤:哈斯克尔
