【问题标题】:How to add instances of sub types that have common base class to the same list in FSharp?如何将具有公共基类的子类型的实例添加到 FSharp 中的同一列表中?
【发布时间】:2016-02-12 11:37:59
【问题描述】:

我有一个名为 Token 的基本抽象类和一些子类型,例如 NumToken,StrToken
我想将他们的实例放在同一个列表中。

我无法声明变量使用let l = list<'a when 'a :> Token>

然后,我写

    let extractToken<'a when 'a :> Token>(lineNum:int, line:string) : 'a list option =
        let mutable result : 'a list = []  

它可以工作,但不能添加元素。result &lt;- new NumToken(lineNum, value) :: result 只是说它需要'a 但这里是NumToken

现在我可以使用new NumToken(lineNum, value) :&gt; Token 并声明Token list
它工作但看起来很难看(我知道 fsharp 不会自动向上转换..)。

list&lt;_ :&gt; Token&gt; 也不起作用,它只接受一种子类型。

谢谢帮助。

【问题讨论】:

    标签: f#


    【解决方案1】:

    当您使用类层次结构对标记进行建模并创建标记列表时,列表的类型需要具体。您可以返回list&lt;Token&gt;list&lt;NumToken&gt;

    具有when 约束的灵活类型很少有用 - 通常,当您有一个函数接受其他函数并返回其他函数产生的任何内容时,所以我认为您在这里不需要它们。您可以使用list&lt;Token&gt; 并写:

    result <- (NumToken(lineNum, value) :> Token) :: result 
    

    也就是说,在 F# 中使用类层次结构对令牌进行建模并不是一个好主意。 F# 支持可区分联合,它更适合此类问题:

    type Token = 
      | NumToken of int
      | StrToken of string
    

    那你就可以写一个函数返回list&lt;Token&gt;,只要写就可以了

    result <- (NumToken 42) :: result
    

    不过,根据您的操作,避免突变也是一个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 2022-01-20
      • 2019-01-17
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      相关资源
      最近更新 更多