2017-10-21 50 views
1

我嘗試使用下面的代碼打印在Haskell鏈表:變量未在範圍上的錯誤使用功能衛士

data List = Node {value:: Double, next:: List} 
      | Empty 

printList :: List -> String 
printList x | x == (Node v n) = show v ++ " " ++ printList n 
      | otherwise = show '_' 

和獲取編譯錯誤:

:load scratch.hs 
[1 of 1] Compiling Main    (scratch.hs, interpreted) 

scratch.hs:5:26: error: Variable not in scope: v :: Double 

scratch.hs:5:28: error: Variable not in scope: n :: List 

scratch.hs:5:38: error: Variable not in scope: v 

scratch.hs:5:53: error: Variable not in scope: n :: List 
Failed, modules loaded: none. 

雖然我能夠使用沒有警衛的模式匹配來做同樣的事情。

printList (Node v n) = show v ++ " " ++ printList n 
printList Empty = "" 

第一個代碼有什麼問題?

+0

在'的printList(節點VN)','v'和'N'是參數,但在'x ==(Node vn)'中,它們是兩個未定義的變量。 – ForceBru

+0

@ForceBru所以有辦法區分哪個數據構造函數x正在使用? –

回答

4

通過使用相等性檢查,您不會做模式匹配:有可能兩個不同的模式被認爲是相等的。

所以你可以做的是定義一個模式在你的函數的一個子句的頭部。例如:

printList :: List -> String 
printList (Node v n) = show v ++ " " ++ printList n 
printList _ = show '_'

所以現在哈斯克爾會,因爲如果它與Node v n模式匹配,和一個給定的List檢查,如果這樣解壓元素和分配頭v和尾部n

但是我們仍然可以改進代碼。通常你最好不要使用通配符模式,而是使用所有可能的模式。因爲如果你以後想改變的List定義,編譯器可以給你,你忘了圖案的警告:

printList :: List -> String 
printList (Node v n) = show v ++ " " ++ printList n 
printList Empty = show '_'

我們可以改善的另一件事是在show '_'使用"_"。由於show '_'會將內容加到中。例如:

printList :: List -> String 
printList (Node v n) = show v ++ " " ++ printList n 
printList Empty = "_"

最後,我們還可以使用 「缺點」 建設上有一個單列表附加:

printList :: List -> String 
printList (Node v n) = show v ++ ' ' : printList n 
printList Empty = "_"
+0

但我之前編寫的一段代碼有一個函數參數'x',與數據構造函數行'Meter'比較。代碼如下:'數據MetricUnit = Meter |升| |千克 派生(Show,Eq)''returnMetricSymbol x | x ==米=「m」 | x == Liter =「L」 | x == Kilogram =「kg」' –

+1

@SafwanAhmad:這是因爲(1)你添加了'derving Eq',並且(2)在這裏你只檢查是否相等,你不需要*解壓縮構造函數,沒有參數在你感興趣的代碼中。 –

+0

好吧,我的理解是,在guard語句中使用Data構造函數本質上是創建新變量,而如果我使用相同的Data構造函數作爲函數參數,則它是模式匹配的。這意味着我的代碼在上面的評論中是純粹的機會,因爲'Meter'正在創建一個新變量,與'x'進行比較,並且可以進行比較,因爲我推導出了'Eq'。對? –