簡體   English   中英

Haskell類型變量

[英]Haskell Type Variable

了解Haskell創建Tree代數數據類型:

data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq)

我的理解是a可以是任何類型。

所以我嘗試創建一個treeInsert函數,它根據Side值將Tree放在左側或右側:

data Side = L | R

singletonTree :: a -> Tree a
singletonTree x = Node x EmptyTree EmptyTree

treeInsert :: a -> Tree a -> Tree a
treeInsert x EmptyTree = singletonTree x
treeInsert x@(L, _) (Node a left right) = Node a (treeInsert x left) right -- ERROR
treeInsert x@(R, _) (Node a left right) = Node a left (treeInsert x right)

但是我遇到了一個編譯時錯誤:

    Couldn't match expected type `a' with actual type `(Side, t0)'
      `a' is a rigid type variable bound by
          the type signature for treeInsert :: a -> Tree a -> Tree a
          at File.hs:10:15
    In the pattern: (L, _)
    In an equation for `treeInsert':
        treeInsert x@(L, _) (Node a left right)
          = Node a (treeInsert x left) right
Failed, modules loaded: none.

也許a仍然是任何類型,但我的模式匹配無效?

僅僅因為a可以是Tree a中的任何類型,並不意味着它可以是傳遞給treeInsert的樹中的任何類型。 您需要將其細化為實際允許(L, _)(R, _)模式匹配的類型。

實際上,您可以刪除treeInsert上的類型注釋並進行編譯,之后您可以向GHCi請求:t以獲取正確的類型(然后根據需要重新添加該注釋):

treeInsert :: (Side, t) -> Tree (Side, t) -> Tree (Side, t)
treeInsert :: a -> Tree a -> Tree a

因此, treeInsert將獲取任何類型的值,以及包含相同類型的樹,並生成相同類型的樹。

你的方程試圖將x與模式(L, _)(R, _)相匹配。 可是等等; 這種類型說我可以用我喜歡的任何類型來稱呼它。 我應該能夠像treeInsert ["this", "is", "a", "list", "of", "String"] EmptyTree 如何將[String]類型的東西與(L, _)這樣的模式匹配; 僅適用於表單類型(Side, t0) (對於任何類型t0 )。

調用函數時,像a這樣a類型變量非常靈活; 您可以使用您喜歡的任何類型的任何值,該功能將起作用。

但是你沒有調用 treeInsert ,你正在實現它。 對於實現者來說,像a這樣a類型變量是極其嚴格的而不是靈活的。 這是不可避免的權衡1 來電者可以自由選擇他們想要的任何東西; 實現者必須提供適用於調用者可能選擇的任何代碼的代碼(甚至是調用者程序在完成函數后很長時間內構成的類型)。

因此,您無法針對像(L, _)這樣的模式進行測試。 或任何其他有意義的模式。 你也不能將它傳遞給任何“具體”功能,只能傳遞給接受任何可能類型的其他功能。 所以實際上在treeInsert有類型a -> Tree a -> Tree a ,沒有辦法在你插入的所有值上使用任何屬性來決定它們將去哪里; 對於您可能想要用於決定是將其放在左側樹還是右側樹中的任何屬性,無法保證該屬性將被有意義地定義。

您可能需要根據您可以檢查的內容(例如也傳入的樹的結構)進行插入,或者使用一種為調用者提供較少靈活性的類型,並實際為您提供有關值的信息。重新插入,例如treeInsert :: (Side, t) -> Tree (Side, t) -> Tree (Side, t) ,如ØrjanJohansen所建議的那樣。


1而且這種非常嚴格的限制實際上是Haskell整體上獲得了很大的力量,因為許多真正有用的通用代碼依賴於某些類型的函數無法做到的。

暫無
暫無

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

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