我在F#中具有以下联合和辅助函数:
type ParsedItem =
| Digit of char
| Operator of char
| Alpha of char
| NotParsed of char
let private digits = ['0'..'9']@['.']
let private opers = ['!';'%';'^';'*';'(';')';'+';'=';'<';'>']
let private alphas =['A'..'Z']@['a'..'z']
let (|IsDigitChar|_|) ch =
match List.exists(fun a->a=ch) digits with
| true -> Some IsDigitChar
| _ -> None
let (|IsOperChar|_|) ch =
match List.exists(fun a->a=ch) opers with
| true -> Some IsOperChar
| _ -> None
let (|IsAlphaChar|_|) ch =
match List.exists(fun a->a=ch) alphas with
| true -> Some IsAlphaChar
| _ -> None
let parseChar ch =
match ch with
| IsDigitChar -> Digit(ch)
| IsOperChar -> Operator(ch)
| IsAlphaChar -> Alpha(ch)
| _ -> NotParsed(ch)
但是以下功能无法识别“数字”类型:
let coalesceDigits (dgts: Digit list) =
[|for Digit d in dgts -> d|] |> string
编译器在(dgts: Digit list)
参数上发出以下警告:
The type 'Digit' is not defined'
但是,它还会对函数主体Digit d
中的[|for Digit d in ...
发出以下警告:Incomplete pattern matches on this expression. For example, the value 'Alpha (_)' may indicate a case not covered by the pattern(s).
因此它会将其识别为主体中的ParsedItem
,但不会在声明中?
如何让编译器识别Digit
确实是一种类型,而不必在ParsedItem
之外声明它,或者必须将Digit
和其他声明为自己的类型然后将它们添加到ParsedItem
中,如下所示?
type Digit = Digit of char
[...]
type ParsedItem =
| Digit of Digit
| Operator of Operator
| ... (etc)
答案 0 :(得分:4)
Digit
不是一种类型。
ParsedItem
是一种类型,但Digit
不是,Operator
,Alpha
和NotParsed
都不是
使用该语法,您定义了类型ParsedItem
,其值可以有四种样式-Digit
,Operator
,Alpha
或NotParsed
您可以通过指定要创建的风味以及风味所需的任何参数来创建ParsedItem
类型的新值(在您的情况下,所有风味都有一个char
参数),如下所示:
let item1 = Digit 'a'
let item2 = Operator 'b'
// and so on
在此示例中,item1
和item2
均为类型ParsedItem
的值。它们是不同类型的 not 值。
如果您的值类型为ParsedItem
,则可以通过模式匹配来找出其味道:
let whatIsIt item =
match item with
| Digit c -> "It's a digit!"
| Operand c -> "It's an operand!"
| Alpha c -> "It's an alpha!"
| NotParsed c -> "Not parsed :-/"
printfn "%s" (whatIsIt item1) // prints "It's a digit!"
printfn "%s" (whatIsIt item2) // prints "It's an operator!"
如果在编写模式匹配时错过了风味,编译器会抓住您:
let whatIsIt item =
match item with
| Digit c -> "It's a digit!"
// Warning: incomplete pattern match
在收到此警告的情况下,编译器告诉您:“我看到您已经定义了item
恰好是Digit
时该怎么办,但是我应该如何处理其他三种呢?”
这也是代码中发生的情况:您在Digit d
上进行了模式匹配,但没有具体说明对其他口味的处理方式。
现在,我不知道您要在这里实现什么,并且您的代码有点荒谬(出于上述原因),所以我能做的最好的事情就是解释您对语言语法的误解。如果您详细说明自己的实际目标,我也许可以建议一种正确的编码方式。
答案 1 :(得分:2)
Digit
不是类型,它是类型ParsedItem
的标签/大小写
因此,您需要显式创建类型Digit
,并在Digit
的标记ParsedItem
中使用它。编译器知道如何区分它,因此同名Digit
没问题。
type Digit = DigitValue of char
type ParsedItem =
| Digit of Digit ...
let coalesceDigits (dgts: Digit list) =
[|for (DigitValue d) in dgts -> d|] |> string