簡體   English   中英

haskell類型聲明的使用方式與python類/函數文檔相同嗎?

[英]Are haskell type declarations used the same way as python class/function documentation?

我正在使用“了解你一個haskell教程”並已到達類型聲明部分。 我知道他們改變了GHCI給你錯誤信息的方式,但它們是否也會影響實際功能的運作方式? 如果不是,它本質上就像一個python函數文檔用“”“”“”“寫在”def someFunction(x)下面:“? - 只是一個例子

示例代碼:

removeNonUppercase :: [Char] -> [Char]  
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]

編輯:我問這個是因為教程解釋了haskell在編譯時是類型推斷的。

簽名不僅適用於文檔(即使它們對此也非常有用)。 它們由編譯器強制執行,這意味着通過添加簽名,您可以使您的函數類型比其他方式更具限制性。 玩具示例:

add x y = x + y

addInt :: Int -> Int -> Int
addInt x y = x + y
*Main> :t add
add :: Num a => a -> a -> a
*Main> add 2 3
5
*Main> add 2.1 3.1
5.2
*Main> :t addInt
addInt :: Int -> Int -> Int
*Main> addInt 2 3
5
*Main> addInt 2.1 3.1 -- addInt will not accept non-Ints.

<interactive>:23:8:
    No instance for (Fractional Int) arising from the literal ‘2.1’
    In the first argument of ‘addInt’, namely ‘2.1’
    In the expression: addInt 2.1 3.1
    In an equation for ‘it’: it = addInt 2.1 3.1

除此之外,添加類型簽名意味着您將在棘手的情況下獲得更好(即更容易理解)的錯誤,因為編譯器將知道您想要實現什么,而不是自己猜測所有內容。

在某些情況下,如果沒有某些簽名或其他類型注釋的幫助,編譯器無法決定類型。 也許最簡單的例子是:

readAndShow s = show (read s)

如果您嘗試使用它而不指定任何類型...

Foo.hs:6:17:
    No instance for (Show a0) arising from a use of ‘show’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance (GHC.Arr.Ix a, Show a, Show b) => Show (GHC.Arr.Array a b)
        -- Defined in ‘GHC.Arr’
      instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
      instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
        -- Defined in ‘GHC.Real’
      ...plus 26 others
    In the expression: show (read s)
    In an equation for ‘readAndShow’: readAndShow s = show (read s)

Foo.hs:6:23:
    No instance for (Read a0) arising from a use of ‘read’
    The type variable ‘a0’ is ambiguous
    Note: there are several potential instances:
      instance (GHC.Arr.Ix a, Read a, Read b) => Read (GHC.Arr.Array a b)
        -- Defined in ‘GHC.Read’
      instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
      instance (Integral a, Read a) => Read (GHC.Real.Ratio a)
        -- Defined in ‘GHC.Read’
      ...plus 25 others
    In the first argument of ‘show’, namely ‘(read s)’
    In the expression: show (read s)
    In an equation for ‘readAndShow’: readAndShow s = show (read s)
Failed, modules loaded: none.

......它不會起作用。 readString轉換為某種類型,而show則相反。 但是,如果沒有指定read s類型,則編譯器無法確定要將String讀取為哪種類型。 所以你要么需要指定中間類型......

readAndShowAsInt s = show (read s :: Int)
*Main> readAndShowAsInt "2"
"2"

...或者還有別的東西為你挑選類型:

readAndAdd :: String -> Int -> Int
readAndAdd s y = read s + y
*Main> readAndAdd "2" 3
5

在簡單的情況下,類型聲明與Haskell推斷的類型相同,只是文檔+幫助防止混淆錯誤。 但也有例外:

(1)您可以提供比推斷的更嚴格的類型聲明。 例如

squareInt :: Int -> Int
squareInt x = x*x

如果沒有聲明,那將被推斷為Num t => t -> t 但有了它,該函數只能用於Int s,而不能用於任何數字類型。 這有時可用於將函數限制為預期用例,或用於防止類型模糊錯誤。

(2)許多語言擴展需要類型聲明,因為它們超出了推理算法支持的類型系統的部分。 例如,排名n類型:

f :: (forall x. Show x => y) -> (Int, Bool) -> (y, y)
f g (i, b) = (g i, g b)

這還包括標准Haskell功能“多態遞歸”,這意味着使用與最初調用的類型不同的類型遞歸調用函數。

類型聲明是您作為程序員的工具,可以檢查您的代碼。 類型推斷Haskell總是正確的 - 但它可能不是你編寫代碼時的預期。 你可能期望一個Int - > Int - > Int類型的函數,但是你的代碼可能會告訴推理算法函數是類型(Int,Int) - > Int,因為你忘記了某處的括號。

它們也是程序員的一種文檔形式。 有時在編寫代碼時查看函數的類型非常有用。 通常(如果函數名稱很好),您可以通過查看函數的名稱和類型來確定函數應該執行的操作。 文檔仍然非常有用,但是當您開始編寫和閱讀更多功能程序時,類型將成為您用來幫助您理解代碼的東西。

暫無
暫無

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

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