为什么递归模式同义词被接受?

这个问题(从 5 年前开始)问“为什么所有递归模式同义词都被拒绝?” 它的例子仍然被拒绝。用户指南说“模式同义词不能递归定义”。

我有一个被接受的递归模式同义词(GHC 8.10.2)。我可以调用它,它会循环——这并不奇怪。那么为什么它会编译?/对于这样的事情是否有合理的用例?

代码基于2016 年论文的第 2.3 节“多态模式同义词”中的示例。

data JoinList a = JNil | Unit a | JoinList a `JoinTree` JoinList a    deriving (Eq, Read, Show)

我正在尝试定义一个模式同义词Nil。显然JNil是一场比赛。而且JNil ``JoinTree`` JNil,任何JoinTree提供所有叶子的任意嵌套都是JNil.

pattern Nil :: JoinList a
pattern Nil <- JNil
  where Nil = Nil `JoinTree` Nil      -- huh?

wot = Nil `JoinTree` Nil              -- these all compile
wotwot Nil = ()
wotwotwot = wotwot Nil
wotwotwotwot = wotwot wot

尝试调用wot循环,这并不奇怪。试图打电话wotwotwot抱怨Non-exhaustive patterns in function wotwot

完全披露:我在玩什么/我知道这不起作用[另见下文]是:

pattern Nil = JNil                     -- base case matcher, and builder
  where Nil <- Nil `JoinTree` Nil      -- recursion on the matcher, not the builder
                                       -- but can't put `<-` equations after where

以下被拒绝Recursive pattern synonym definition——这是我所期望的

pattern NilRec <- NilRec `JoinTree` NilRec 
  where NilRec = JNil    

无论如何这都行不通:它需要首先匹配NilRec = JNil作为基本情况。


要回答@Noughtmare 的问题“你如何建议......”对他的回答发表评论,我想在上面写上“我在玩什么”的 decl(是的,我知道这是目前非法的语法);并通过两种情况将其脱糖到匹配器中,依次尝试:

case arg of
  { JNil -> ...
  ; Nil `JoinTree` Nil -> ...
  }

请注意,这些情况中的每一个都有一个来自 type 的数据构造函数JoinList。因此递归使用Nil是受保护/中介的,就像通过 ViewPattern 的任何方法一样。(这是 5 年前的 q 所问的。)换句话说:我认为编译器可以从pattern ... = ... where ... <- ....

回答

只有匹配器不能递归,因为这可能导致无限模式匹配(无限大的程序)。的脱糖case x of Nil -> y将是:

  case x of
    JNil -> y
    JoinTree x2 x3 -> case x2 of
      JNil -> case x3 of
        JNil -> y
      JoinTree x4 x5 -> case x4 of
        ...

无限地继续下去。

拥有递归构建器很好,因为它们可以包含任意函数。这可能是一个更简单的示例,可以在不混淆构造函数的情况下显示这一点:

pattern Foo <- ()
  where Foo = let loop = loop in loop

您可以使用ViewPatterns以下命令在模式中允许任意函数:

normJoinList (JoinTree (normJoinList -> JNil) (normJoinList -> JNil)) = JNil
normJoinList x = x

pattern Nil <- (normJoinList -> JNil)
  where Nil = JNil

我认为这可以满足您的要求:

> case Nil `JoinTree` Nil of Nil -> True; _ -> False
True


以上是为什么递归模式同义词被接受?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>