[英]Is “List” specially handled in Haskell's pattern matching?
我是Haskell的新手,希望這個問題不傻。
我已經看到了很多例子,當我有一個列表時,我能夠匹配並將列表的“組合元素”綁定到單個變量:
listSizeDesc :: [a] -> String
listSizeDesc [] = "Emtpy"
listSizeDesc (x:xs) = "Something inside"
但是,我嘗試做類似的事情:
foo :: Int -> String
foo 0 = "Zero"
foo (n - 1) = "next number is " ++ show n
它不起作用。
在我看來,(n-1)和(x:xs)都描述了如何“創建”參數並將“組件”綁定到參數。 List的匹配方式是為了便於遞歸而專門設計的嗎? 因為在我看來,這個匹配/參數綁定邏輯不適用於除(:)之外的其他函數。
您遇到的問題是模式匹配僅適用於數據構造函數。 數據構造函數本質上非常簡單; 它只需要采用數據值並將它們組合在一起。 例如, data Foo = Bar ab
只需要兩個數據並在Foo標簽下將它們組合在一起。 您在第一個示例中使用的(:)
函數不僅僅是一個函數; 它是一個數據構造函數。 它通過向左參數添加左參數來構造新列表。
現在,模式匹配僅僅與此過程相反。 它解構了一種數據類型。 當您在模式中編寫(x:xs)
時,您將提取構造函數最初拼接在一起的兩個數據。 因此,所有模式匹配都會提取構造函數先前拼接在一起的數據。
有一個例外:n + k模式。 在Haskell98中,您被允許使用形式(n + k)的模式。 這是一種任意的例外,它最近被刪除了。 如果您願意,如果包含NPlusKPatterns語言編譯指示,仍可以使用它。
列表類型是帶有構造函數的“Sum type”,類似於:
data List a =
cons a (List a)
| nil
你第一個例子是在數據類型的模式匹配(與語法糖:
)。
第二個示例是整數上的模式匹配,它不是數據類型定義。 在整數上,沒有使用語法的模式。 你可以寫下你的例子:
foo :: Int -> String
foo 0 = "Zero"
foo n = "next number is " ++ show (n+1)
如果您使用以下數據類型對整數進行編碼,請注意:
data Nat = Zero | Succ Nat deriving (Show)
然后,您可以根據需要使用模式匹配。
foo :: Nat -> String
foo Zero = "Zero"
foo n@Succ(p) = "next number is " ++ show(n)
這里的模式Succ(p)
起n-1
的作用。
已經有了一些很好的答案,所以我不會理會主要問題。 這不是最佳用途,但您嘗試做的事情可以通過視圖模式完成。
{-# LANGUAGE ViewPatterns #-}
foo :: Int -> String
foo 0 = "Zero"
foo (pred -> n) = "Next number is " ++ show n
只是為了盡可能簡單地說:
字面上的列表是一系列連接。 數字可以等於算術運算的結果。 區別在於a : b
的結果只是a : b
。
更詳細:
列表和(:)根本不是特例。 讓我們自己做:
data List2 a = End -- equivalent of "[]"
| Cat a (List2 a) -- non-infix ":"
deriving (Show)
所以[1, 2, 3]
,= = (1 : (2 : (3 : [])))
,寫成:
a = Cat 1 (Cat 2 (Cat 3 End))
就像模式匹配(x:xs)
,我們可以模式匹配List2:
newTail End = End
newTail (Cat _ x) = x
測試一下:
*Main> tail [1,2,3]
[2,3]
*Main> newTail a
Cat 2 (Cat 3 End)
moo :: Int -> String
moo 0 = "Zero"
moo n = "next number is " ++ show (n + 1)
n - 1
是普通的函數應用程序,而不是模式。 以前是一個例外+
,這可能是你要去的模型。 你可以寫類似的東西
goo :: Int -> String
goo 0 = "Zero"
goo (n+1) = "previous number is " ++ show n
在hugs
; 如果你包括pragma,你仍然可以用ghc
做到這一點
{-#LANGUAGE NPlusKPatterns#-}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.