我正在阅读使用以下示例的教程(我将对其进行概括):

f :: Foo -> (Int, Foo)
...
fList :: Foo -> [Int]
fList foo = x : fList bar
  where
    (x, bar) = f foo

我的问题在于,您似乎可以在获取它们的元组之外按名称引用 xbar 。如果我的猜测正确的话,这似乎就像在破坏其他语言的参数列表一样。 (换句话说,我不必执行以下操作:)
fList foo = (fst tuple) : fList (snd tuple)
      where
        tuple = f foo

我对这种行为是否正确?我从未在我阅读的教程/书籍中看到它提到过。有人可以指出我有关该主题的更多信息吗?

编辑 :任何东西(列表、数组等)都可以用类似的方式解构,还是只能用元组来解构?

最佳答案

看到您的编辑,我想您要问的是 Pattern matching
并回答您的问题:是的,您可以构造任何东西,也可以使用构造函数“解构”。例如,您可能熟悉这种形式的模式匹配:

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
请注意,最后两个示例与第一个 to 有点不同,因为当您使用空列表调用它们时,它们会给出不同的错误消息。

尽管这些示例特定于列表,但您可以对其他数据类型执行相同操作,如下所示:
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 调用最后一个函数也会崩溃。
总结;如果您可以使用构造函数(如列表的 (:)[],或元组的 (,),或 Maybe 的 NothingJust)创建某些东西,您可以使用这些相同的构造函数以多种方式进行模式匹配。

10-08 08:38
查看更多