在Haskell中解构元组时,元素可以在哪里使用?
-
08-07-2019 - |
题
我正在阅读使用以下示例的教程(我将稍微概括一下):
f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
where
(x, bar) = f foo
我的问题在于,似乎您可以在获取它们的元组之外引用 x
和 bar
。如果我的猜测是正确的,这似乎就像在其他语言中解构参数列表一样。 (换句话说,我没有做以下事情:)
fList foo = (fst tuple) : fList (snd tuple)
where
tuple = f foo
我对这种行为是对的吗?在我读过的教程/书籍中,我从未见过它。有人能指出我有关这个问题的更多信息吗?
编辑:可以用类似的方式对任何内容(列表,数组等)进行解构,还是只能用元组执行此操作?
解决方案
看到你的编辑,我想你的问题是模式匹配。
回答你的问题:是的,你可以构建任何东西,你也可以使用构造函数“解构”。例如,您可能熟悉这种模式匹配形式:
head :: [a] -> a
head (x:xs) = x
head [] = error "Can't take head of empty list"
但是,有更多地方可以使用模式匹配,其他有效的符号是:
head xs = case xs of
(y:ys) -> y
[] -> error "Can't take head of empty list"
head xs = let (y:ys) = xs
in y
head xs = y
where
(y:ys) = xs
请注意,最后两个示例与第一个示例略有不同,因为当您使用空列表调用它们时,它们会给出不同的错误消息。
虽然这些示例特定于列表,但您可以对其他数据类型执行相同操作,例如:
first :: (a, b) -> a
first tuple = x
where
(x, y) = tuple
second :: (a, b) -> b
second tuple = let (x, y) = tuple
in y
fromJust :: Maybe a -> a
fromJust ma = x
where
(Just x) = ma
同样,如果用 Nothing
调用它,最后一个函数也会崩溃。
总结;如果你可以使用构造函数创建一些东西(比如(:)
和 []
用于列表,或者(,)
用于元组,或没有什么
和只是
for Maybe),你可以使用那些相同的构造函数以各种方式进行模式匹配。
其他提示
我对这种行为是对的吗?
是。但是,名称仅存在于您已定义它们的块中。在您的情况下,这意味着应用 where
子句的逻辑单元,即 fList
中的表达式。
另一种看待它的方法是像这样的代码
x where x = 3
大致相当于
let x = 3 in x
是的,你是对的。在where子句中绑定的名称对于where子句之前的完整声明是可见的。在您的情况下,这些名称是 f
和 bar
。
(学习Haskell的一个难点在于,不仅允许使用源代码中的变量,而是在定义这些变量的位置之前的位置使用变量。)
有关详细信息,请参阅 Haskell 98报告或在 haskell.org
中找到的众多精彩教程之一。