Haskell where 子句中的类型映射(-> 运算符)?

Haskell type-mapping (-> operator) in where clause?

我正在尝试理解 this article 中的代码。它解释了归纳图的使用,这看起来非常好,并且在某些时候它定义了对归纳图的深度优先搜索。它的代码如下:

dfs :: Graph.Node -> Gr a b -> [Node]
dfs start graph = go [start] graph
  where go [] _                            = []
        go _ g | Graph.isEmpty g           = []
        go (n:ns) (match n -> (Just c, g)) =
          n : go (Graph.neighbors' c ++ ns) g
        go (_:ns) 

我不明白这两行:

        go (n:ns) (match n -> (Just c, g)) =
          n : go (Graph.neighbors' c ++ ns) g

它似乎正在定义函数 go,它以列表作为第一个参数,由 (n:ns) 进行模式匹配。但是,第二个参数我不明白:(match n -> (Just c, g))。这里的运算符 -> 是什么意思?通过查找运算符,它可以是以下三种情况之一:

由于没有case语句,也没有lambda表达式的反斜杠转义变量,只能是函数类型映射运算符。在这种情况下,我不明白它是如何将值绑定到这些变量的,cg?它到底是什么意思,怎么会在争论中呢?

提前致谢!

在这种情况下,

-> 既不表示 function-type 也不表示 lambda-definition 也不表示 case-mapping。这是一个 view pattern.

go (n:ns) (match n -> (Just c, g)) =
      n : go (Graph.neighbors' c ++ ns) g

相当于

go (n:ns) g'
  | (Just c, g) <- match n g'
        = n : go (Graph.neighbors' c ++ ns) g

其中 pattern guard (Just c, g) <- match n g' 又是

的缩写
go (n:ns) g' = case match n g' of
   (Just c, g) -> n : go (Graph.neighbors' c ++ ns) g
   (Nothing, g) -> ...

其中 Nothing 子句需要代表 go 定义的后面的子句。

这是一个view pattern。这个扩展允许我们在匹配之前以某种方式转换参数。

如果没有这个扩展,代码将不得不这样写:

go (n:ns) g' =
  case match n g' of
    (Just c, g) -> ...
    ...

这有点冗长。