繁体   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