簡體   English   中英

Haskell何時需要類型簽名?

[英]When are type signatures necessary in Haskell?

許多介紹性文本將告訴您,在Haskell類型簽名中,“幾乎總是”是可選的。 有人可以量化“幾乎”部分嗎?

據我所知, 唯一需要顯式簽名的就是消除類型類的歧義。 (正在read . show的典型示例。show。)還有其他我沒有想到的情況嗎?

(我知道,如果您超越Haskell 2010,會有很多例外情況。例如,GHC永遠不會推斷N級類型。但是N級類型是語言的擴展,不是官方標准的一部分[尚未]。 )

通常,多態遞歸需要類型注釋。

f :: (a -> a) -> (a -> b) -> Int -> a -> b
f f1 g n x = 
    if n == (0 :: Int)
    then g x
    else f f1 (\z h -> g (h z)) (n-1) x f1

(來源:帕特里克·庫索)

注意遞歸調用看起來多么嚴重類型(!):它調用本身帶有五個參數,盡管f只有4級 然后記住,可以使用c -> d實例化b ,這會導致出現一個額外的參數。

上面的人為例子計算

f f1 g n x = g (f1 (f1 (f1 ... (f1 x))))

其中f1被應用了n次。 當然,有一種編寫等效程序的簡單得多的方法。

單態限制

如果啟用了MonomorphismRestriction ,則有時需要添加類型簽名以獲得最通用的類​​型:

{-# LANGUAGE MonomorphismRestriction #-}
-- myPrint :: Show a => a -> IO ()
myPrint = print
main = do
  myPrint ()
  myPrint "hello"

這將失敗,因為myPrint是單態的。 您需要取消注釋類型簽名以使其起作用,或禁用MonomorphismRestriction

幻影約束

當您將具有約束的多態值放入元組時,元組本身將變為多態並具有相同的約束:

myValue :: Read a => a
myValue = read "0"

myTuple :: Read a => (a, String)
myTuple = (myValue, "hello")

我們知道,約束影響的元組的第一部分,但影響第二部分。 不幸的是,類型系統不知道這一點,如果您嘗試這樣做,將會抱怨:

myString = snd myTuple

即使直覺上會期望myString只是一個String ,類型檢查器仍需要專門化類型變量a並確定約束是否真正得到滿足。 為了使該表達式起作用,需要注釋sndmyTuple的類型:

myString = snd (myTuple :: ((), String))

可以肯定,您可以在Haskell中推斷類型。 換句話說,編譯器可以計算出所需的類型。

但是,在Haskell中,也存在多態類型類,根據返回類型,函數以不同的方式起作用。 這是Monad類的示例,盡管我還沒有定義所有內容:

class Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b
    fail :: String -> m a

我們給了很多帶有類型簽名的功能。 我們的工作是為可以視為Monad的不同類型進行實例聲明,例如Maybe t[t]

看一下這段代碼-它不能像我們期望的那樣工作:

return 7

那是Monad類的一個函數,但是因為有多個Monad,所以我們必須指定所需的返回值/類型,否則它會自動成為IO Monad。 所以:

return 7 :: Maybe Int
-- Will return...
Just 7

return 6 :: [Int]
-- Will return...
[6]

這是因為[t]Maybe都已在Monad類型類中定義。

這是另一個示例,這一次來自隨機類型類。 此代碼引發錯誤:

random (mkStdGen 100)

因為random返回Random類中的某些內容,所以我們必須使用想要的StdGen對象StdGen定義想要返回的類型:

random (mkStdGen 100) :: (Int, StdGen)
-- Returns...
(-3650871090684229393,693699796 2103410263)

random (mkStdGen 100) :: (Bool, StdGen)
-- Returns...
(True,4041414 40692)

在網上學習Haskell可以找到所有這些內容,盡管您需要做一些長時間的閱讀。 我幾乎100%地確定,這是唯一需要類型的時間。

暫無
暫無

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

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