如何在 F# 中编写返回不同类型的函数?

3

我用F#编写了一个扫描器。目前它返回一个由多个元组组成的列表,每个元组的类型为(Token, string)。

理想情况下,我希望返回一个可能包含不同类型的元组列表。例如:

(Token, string) 
//if it's an identifier

(Token, float)
//if it's a float. 

(Token, int)
//etc

所以,基本上我想返回类型(Token, _),但我不确定如何指定它。现在它只有错误报告不匹配的类型。我正在查看我的书和wikibooks,但我不确定这叫什么。
如果真的不可能,我想稍后可以转换类型,但我希望可以通过这种方式直接返回内容。

1
你能展示一下你的函数的样例输入和期望输出吗? - Juliet
3个回答

13

在F#中,有两种相对容易的方法来处理这个问题。其中一种是创建一个辨别联合(discriminated union):

type Expression =
| Identifier of string
| FloatValue of float
| IntValue of int
| ...

然后定义您的函数,使其返回一个 (Token * Expression) list。另一种可能性是将所有内容装箱为对象,然后返回一个 (Token * obj) list。这对于列表的生产者来说稍微容易些,但对于消费者来说更加烦人。


好的,语法问题。我尝试做这个: let(Token * 表达式)函数名 = .... 和 (Token * 表达式)函数名 = ....试图指定返回类型,但两者都报错。我只是想在这里指定返回类型。 - jeff
@jeff:在F#中,你可以使用let expression : type = ...为let-bound表达式分配类型。在你的情况下,这可能看起来像let functionName : string -> Token * Expression = fun input -> ...let functionName (input : string) : Token * Expression = ...。然而,在大多数情况下,F#将能够为你推断出类型,因此你不需要声明它们。 - kvb
好的,我尝试了类似于这样的东西: let functionName (txt: string) : Token * Expression = ...codes... (<Token> , <string>) 在VS2010中,它会强调显示字符串并说:“此表达式应具有Expression类型,但此处具有string类型”我肯定在您原始回复中所示的定义中包含了字符串: type Expression = ... | strVal of string - jeff
1
@jeff:你必须在函数内使用构造函数,而不仅仅是返回字符串。也就是说,如果你试图返回一个字符串值s,你应该返回strVal s,以便返回的值具有类型Expression而不是string - kvb
太棒了,你真是个救命稻草! - jeff

4

我认为像kvb建议的那样使用区分联合类型是正确的方法。补充一些信息,当在F#中编写扫描器时,通常会定义一个名为Token的令牌类型,该类型列出了各种可能携带类似信息的令牌:

type Token = 
// Some toknes with no additional information
| LParen | RParen | Begin | End
// Some tokens with additional values
| Identifier of string
| IntValue of int
| ...

然后您完全无需将值单独表示为令牌,只需使用令牌列表即可。

1
作为对之前答案的补充,可以看一下Choice类型(以及Choice1of3等Choice情况)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接