在Haskell的模式匹配中是否特别处理了"List"?

Adr*_*hum 19 haskell pattern-matching

我是Haskell的新手,希望这个问题不傻.

我已经看到了很多例子,当我有一个列表时,我能够匹配并将列表的"组合元素"绑定到单个变量:

listSizeDesc :: [a] -> String
listSizeDesc [] = "Emtpy"
listSizeDesc (x:xs) = "Something inside"
Run Code Online (Sandbox Code Playgroud)

但是,我尝试做类似的事情:

foo :: Int -> String
foo 0 = "Zero"
foo (n - 1) = "next number is " ++ show n
Run Code Online (Sandbox Code Playgroud)

它不起作用.

在我看来,(n-1)和(x:xs)都描述了如何"创建"参数并将"组件"绑定到参数.List的匹配方式是为了便于递归而专门设计的吗?因为在我看来,这个匹配/参数绑定逻辑不适用于除(:)之外的其他函数.

Jef*_*rka 18

您遇到的问题是模式匹配仅适用于数据构造函数.数据构造函数本质上非常简单; 它只需要采用数据值并将它们组合在一起.例如,data Foo = Bar a b简单地获取两个数据并在Foo标签下将它们组合在一起.在(:)你在你的第一个例子中使用的功能不仅仅是一个功能更多; 它是一个数据构造函数.它通过向左参数添加左参数来构造新列表.

现在,模式匹配仅仅与此过程相反.它解构了一种数据类型.当您(x:xs)在模式中写入时,您将提取构造函数最初拼接在一起的两个数据.因此,所有模式匹配都会提取构造函数先前拼接在一起的数据.

有一个例外:n + k模式.在Haskell98中,您被允许使用形式(n + k)的模式.这是一种任意的例外,它最近被删除了.如果您愿意,如果包含NPlusKPatterns语言编译指示,仍可以使用它.


Pie*_*rre 14

列表类型是带有构造函数的"Sum type",类似于:

data List a =
     cons a (List a)
   | nil
Run Code Online (Sandbox Code Playgroud)

您的第一个示例是数据类型的模式匹配(具有语法糖 :).

第二个示例是整数上的模式匹配,它不是数据类型定义.在整数上,没有使用语法的模式.你可以写下你的例子:

foo :: Int -> String
foo 0 = "Zero"
foo n = "next number is " ++ show (n+1)
Run Code Online (Sandbox Code Playgroud)

如果您使用以下数据类型对整数进行编码,请注意:

data Nat = Zero | Succ Nat deriving (Show)
Run Code Online (Sandbox Code Playgroud)

然后,您可以根据需要使用模式匹配.

foo :: Nat -> String
foo Zero = "Zero"
foo n@Succ(p) = "next number is " ++ show(n)
Run Code Online (Sandbox Code Playgroud)

这里的模式Succ(p)起着作用n-1.

  • 最后一个例子是倒退的.为了匹配OP想要的,模式应该是'n`并且函数应该显示`Succ n`. (2认同)

Dan*_*ton 5

已经有了一些很好的答案,所以我不会理会主要问题.这不是最佳用途,但您尝试做的事情可以通过视图模式完成.

{-# LANGUAGE ViewPatterns #-}

foo :: Int -> String
foo 0 = "Zero"
foo (pred -> n) = "Next number is " ++ show n
Run Code Online (Sandbox Code Playgroud)