我正在阅读使用以下示例的教程(我将稍微概括一下):

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 中找到的众多精彩教程之一。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top