【发布时间】:2021-07-24 10:03:35
【问题描述】:
这个问题(从 5 年前开始)问'Why are all recursive pattern synonyms rejected?',它的例子仍然被拒绝。用户指南说"Pattern synonyms cannot be defined recursively."
我有一个被接受的递归模式同义词 (GHC 8.10.2)。我可以调用它,它会循环 - 不足为奇。那么为什么它会编译呢?/这样的东西有合理的用例吗?
代码基于2016 paper 的第 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 的 q“你会如何建议......”对他的回答的评论,我想写上面的 decl '我在玩什么'(是的,我知道这是目前非法的语法);并将其脱糖到具有 两个 案例的匹配器中,依次尝试:
case arg of
{ JNil -> ...
; Nil `JoinTree` Nil -> ...
}
请注意,每种情况都有一个来自JoinList 类型的数据构造函数。因此,Nil 的递归使用受到保护/中介,就像通过 ViewPattern 的任何方法一样。 (这是 q 5 年前的问题。)换一种说法:我认为编译器可以从 pattern ... = ... where ... <- ... 生成 ViewPattern。
【问题讨论】:
-
请注意,
pattern ... <- ... where ... = ...表示法分别定义了匹配器(带箭头)和构建器(带等号),它不是您似乎建议的基本案例递归案例拆分。 -
“将其脱糖到具有两个案例的匹配器”——但您建议的脱糖仍然包含糖!
-
@Daniel "你的 [我的] 建议脱糖" 我在这里做了一个尝试gitlab.haskell.org/ghc/ghc/-/issues/12203#note_366851