为什么不能非局部活动模式在F#中进行参数化?局部、参数、模式

2023-09-04 07:22:33 作者:~爱过了_也伤透了℡

下面的F#code ++工程,如我所料,印刷`匹配为A:

The following F# code works as I expected, printing `Matched as 'A':

let (|Char|_|) convf = function
    | LazyList.Nil -> None
    | LazyList.Cons (x, _) -> Some (convf x)

let test = function
    | Char System.Char.ToUpper x -> printfn "Matched as %A" x
    | _ -> printfn "Didn't match"

test (LazyList.of_list ['a'])

不过,如果我更改字符从部分活跃的方式,以一个完整的活动模式如下:

However, if I change Char from a partial active pattern to a complete active pattern as follows:

let (|Char|NoChar|) convf = function
    | LazyList.Nil -> NoChar
    | LazyList.Cons (x, _) -> Char x

let test = function
    | Char System.Char.ToUpper x -> printfn "Matched as %A" x
    | NoChar System.Char.ToUpper -> printfn "Didn't match"

test (LazyList.of_list ['a'])

那么code编译失败,给下面的错误信息:错误FS0191:只有激活模式返回只有一个结果是可以接受的参数

这个例子可能看起来有点做作,但它是一个活跃的格局我试图在Prolog的词法分析器我一直在我的业余时间使用的简化版本。我可以很容易地重写我的code,以避免这个问题,但我很好奇,为什么这样的code是不允许的。

This example may look somewhat contrived, but it's a simplified version of an active pattern I tried to use in a Prolog lexer I've been working on in my spare time. I can easily rewrite my code to avoid this problem, but I'm curious about why this sort of code is disallowed.

更新:的较新版本的F#似乎已经改名为这个错误:

Update: the newer versions of F# seem to have renamed this error:

错误FS0722:只有激活模式返回只有一个结果是可以接受的参数

推荐答案

NB。这正是Brian说,但在一个更清晰的方式希望说明。的

我记得登录precisely这个问题上的错误,并IIRC这是唐赛姆不得不说的事。

I recall logging a bug on precisely this issue and IIRC this is what Don Syme had to say on the matter.

一个多情况下,主动模式是从一​​些输入值的转换功能分为多个输出值中的一个。在你的榜样,任何字符转换为字符的情况下或NoChar情况。

A multi-case active pattern is a conversion function from some input value into one of several output values. In your example, any character is converted to the Char case or the NoChar case.

这样做的好处是,F#编译器调用多情况下,主动模式功能,一次就可以大致判断明年评估哪种模式匹配规则。

The benefit of this is that the F# compiler calls the multi-case active pattern function once and can then generally determine which pattern match rule to evaluate next.

然而,如果你让一个参数,那么你需要评估多情况下,主动模式的每一个模式匹配规则。

If you allow a parameter however, then you need to evaluate the multi-case active pattern for every pattern match rule.

所以,想象一下以下

match input with
| Alpha "foo" -> ...
| Bravo "bar" -> ...

在评估(|阿尔法|布拉沃|)富返回布拉沃,那么第一个规则不匹配。 Likeways(|阿尔法|布拉沃|)栏中的返回阿尔法,那么第二条规则就不是非此即彼匹配。所以,你真的没有多的情况下主动模式。就在paramterized,局部活跃格局。 (由于一些输入的预期图案情况下也不会打了。)

When evaluating (|Alpha|Bravo|) "foo" returned 'Bravo', then the first rule wouldn't match. Likeways (|Alpha|Bravo|) "bar" returns 'Alpha', then the second rule wouldn't match either. So you don't really have a multi-case active pattern. Just a paramterized, partial active pattern. (Because for some inputs the expected pattern-case won't be hit.)

因此​​,当用不构成一个整体非常有意义的语言的一个角落里遇到,实际上可更清晰的部分,参数化的活动模式。该功能未添加到语言

So when confronted with a corner of the language that doesn't make a whole lot of sense, and in fact can be made much clearer by the partial, parameterized active pattern. The feature wasn't added to the language.