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