[英]Haskell tuple not matching with function argument
我是Haskell的新手,所以它可能是顯而易見的,但我做了廣泛的Prolog,所以我對這一個感到困惑......
使用GHCi時,我創建了以下函數(1):
Prelude> let find k t = head [v | (k',v) <- t, k == k'] -- Definiton of find
find :: Eq a1 => a1 -> [(a1, a)] -> a
Prelude> find 2 [(1,11),(2,22)] -- Invocation of find
22
這是預期的。 然后我嘗試從定義中刪除k':
Prelude> let find2 k t = head [v | (k,v) <- t]
find2 :: t -> [(t1, a)] -> a
Prelude> find2 2 [(1,11),(2,22)]
11
然后我非常驚訝地看到值2
實際上與1
相匹配。 為了確保我不希望不可能,我也嘗試以下內容以確認在Haskell中可以進行部分匹配,看起來實際情況如下:
Prelude> head [v | (2,v) <- [(1,11),(2,22)]]
22
我還注意到函數聲明的不同之處。 我添加了所需的信息,因此find
和find2
聲明看起來完全相同。 但結果仍然破碎(2,_)
matchnig (1,11)
:
Prelude> let find2 :: Eq a1 => a1 -> [(a1, a)] -> a; find2 k t = head [v | (k,v) <- t]
find2 :: Eq a1 => a1 -> [(a1, a)] -> a
Prelude> find2 2 [(1,11),(2,22)]
11
如何能2
選配1
通過任何手段?
(1)上述功能來自優秀的“Haskell編程”第93頁
是的,Haskell模式匹配與Prolog模式匹配根本不同。
在Haskell中,模式中的變量指的是將由匹配綁定的新變量,而不是必須匹配的現有變量。 所以,表達式:
let x = 5 in case (1,2) of (x,y) -> "matched!" -- gives "matched!"
將始終評估為“匹配!”。 那是因為x
in (x,y)
剛剛綁定到1
,而不是與x
的“現有”外部定義的值相比,如下所示:
let x = 5 in case (1,2) of (x,y) -> x -- gives "1"
數字常量的行為是不同的:
case (1,2) of (5,y) -> "matched!" -- match fails
以及其他構造函數:
case (True,2) of (False,y) -> "match!" -- match fails
這不是“重新綁定”,而是必須匹配模式匹配才能成功。 這是字母數字構造函數以大寫字母開頭的眾多原因之一:否則,確定模式是否涉及與現有構造函數匹配或重新綁定到新變量將非常困難。
這適用於任何上下文中的模式匹配,無論是上面的case表達式還是像這樣的函數定義:
let x = 5
f x = "hi" -- defines `f` for any `x`, not just `f 5`
或列出你的例子的理解。 在表達式中:
[v | (k,v) <- [(1,2),(3,4)]] -- gives [(1,2),(3,4)]
變量k
和v
將始終是新的,因此將綁定到任何元組, 盡管 k
或v
有任何外部的現有定義。 如果使用-Wall
(特別是-Wname-shadowing
)打開警告,這將提醒您陰影綁定。 如果用常量(或其他構造函數)替換k
,它的行為會有所不同:
[v | (3,v) <- [(1,2),(3,4)]] -- only gives [(3,4)]
你可能不喜歡它,但這就是Haskell的工作方式。
謝謝你的幫助! 經過一些搜索,我也發現這個答案很有用: 如何在Haskell中的函數中重新分配變量?
創建一個具有相同名稱的新變量,該變量將隱藏前一個變量。 但第一個變量仍然存在,在某些情況下仍然可以訪問...
所以這確實遠離Prolog,是的以下標志是有益的:
Prelude> :set -fwarn-name-shadowing
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.