簡體   English   中英

在Haskell的模式匹配中是否特別處理了“List”?

[英]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.

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