這裏有兩個問題。首先,數據類型:
data Tree a = Nil | Node a (Tree left) (Tree right) deriving (Eq, Show, Read)
-- ^left? ^right?
在您的數據定義,您使用的left
和right
,但這些都是在數據定義的頭部形成不,因此這些不會打字參數。你可能想說:
data Tree a = Nil
| Node { value :: a, left :: Tree a, right :: Tree a}
deriving (Eq, Show, Read)
但現在我們仍然得到一個錯誤:
hs.hs:5:1: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘get’: Patterns not matched: _ (Node _ _ _)
Ok, modules loaded: Main.
這裏的問題是,哈斯克爾不知道兩個值只能是<
,==
或>
)。
如果你寫Ord
的instance
,那麼你有一個「聯繫人」,你將定義一個總訂貨。換句話說,對於任何兩個值x
和y
,它認爲x < y
,x > y
或x == y
。然而問題是Haskell確實不是知道的。對於Haskell,函數(<)
,(==)
或(>)
中的任何函數都可導致True
或False
。因此 - 因爲編譯器是總是保守 - 它會考慮有兩個值的情況下,使所有x < y
,x == y
和x > y
失敗(說你假設會寫foo x y
,bar x y
和qux x y
那麼這絕對會偏偏這是因爲它們三個黑匣子函數)。您可以通過在最後一種情況下寫otherwise
解決它:
get :: Ord a => a -> Tree a -> Maybe a
get _ Nil = Nothing
get x (Node v lt rt)
| x == v = Just x
| x < v = get x lt
| otherwise = get x rt
otherwise
是True
的別名因此沒有可能不採取該分支。所以,現在的保守編譯理解的是,無論什麼樣的x
和y
的值,它總是會一些分支,因爲如果不採取前兩種,它會肯定取最後一個。
你可能會認爲這是奇怪的,但由於通常不會在正式語言(僅在文檔中,因此自然語言)中規定的合同,編譯器沒有意味着要知道:你可以作爲一個程序員決定不尊重合同(但請注意,這是一個壞主意非常)。即使你通常以程序員的身份編寫正式合同,你仍然可以決定不尊重它,而且編譯器不能總是對正式合同進行必要的邏輯推理。
你能顯示你得到的警告嗎?爲什麼在你的函數簽名中使用'AATree'而不是'Tree'? –
對不起,我複製了錯誤的代碼,我改變了它,但它只是aatree/tree的區別! – mistysch
警告:警告:[-Wincomplete-patterns] 模式匹配並非詳盡 在'get'的等式中:模式不匹配:_(節點_ _ _) – mistysch