如何从使类型别名更具体的联合类型中解包泛型类型别名?

How do I unwrap a generic type alias from a union type which makes the type alias more specific?

我有类型 Model,它描述了通用类型别名 ModelFields 的两种可能状态。我想从 Model 类型的实例中提取通用 ModelFields 记录。

type Model endValue stats
  = ShowEndValues (ModelFields Organism endValue)
  | ShowStatistics (ModelFields Rank stats)

type alias ModelFields object results =
  { results : List results
  , objects : List object
  , cellValue : results -> String
  , location : Maybe (Rank, Rank)
  }

getModelFields : Model endValue stats -> ModelFields object results
getModelFields model =
  case model of
    ShowEndValues modelFields ->
      modelFields 
    ShowStatistics modelFields ->
      modelFields

但是 Elm 不允许它对每个 case 表达式说

TYPE MISMATCH - Something is off with the 1st branch of this `case` expression:

55|       modelFields 
          #^^^^^^^^^^^#
This `modelFields` value is a:

    ModelFields #Organism# #endValue#

But the type annotation on `getModelFields` says it should be:

    ModelFields #object# #results#

#Hint#: Your type annotation uses type variable `object` which means ANY type of
value can flow through, but your code is saying it specifically wants a
`Organism` value. Maybe change your type annotation to be more specific? Maybe
change the code to be more general?

所以我的问题是:如何从 Model 得到 ModelFields?还是我做的事情存在根本性的缺陷?

更新。我正在尝试建模的详细信息。

我有 Organism 类型的对象。它们被分组为 Ranks。我的服务器对 Organism、i.g 进行了一些成对分析。计算两个 Organism 之间的 SimilarityDistance。我想在不同页面的两个 table 中显示这些分析的结果,一页用于 Similarity 分析,一页用于 Distance 分析。这意味着 table 应该可以重复使用以接受任何形式的分析结果。 另一方面,这些 table 有一个共同的模式。它们可以处于两种状态:

  1. 显示 Organism 之间的成对比较(endValue in Model)的具体结果,因此 table 的行和列代表 Organism s.
  2. 显示 Organism 组 (Ranks) 之间的统计值(例如平均值或标准差,stats in Model),在本例中 table的行和列代表Ranks.

显示哪些 RankOrganism 取决于 ModelFieldslocation 字段。用户可以单击一个按钮,我想更改 update 函数中的 location。此导航更改可能会在 ShowEndValuesShowStatistics 状态之间切换。这就是为什么我试图从 Model 构造函数中解开 ModelFields 的原因。我附上了一个简单的插图,希望它有助于澄清。

这确实不行

getModelFields 函数中的 model 值的类型为 Model endValue stats。这意味着它将是 ShowEndValues 变体,包含 ModelFields Organism endValue 类型的值,或者是 ShowStatistics 包含类型 ModelFields Rank stats 的值的变体。 case 表达式的每个分支解压一个变体并输出 modelFields 值。

现在,让我们尝试确定 case 表达式的类型。我们查看每个分支返回的类型,并尝试找到包含这两种类型的类型(统一它们)。乍一看,它看起来很有希望:两个值都采用 ModelFields a b 形式,因此我们将递归地尝试统一每个子类型。这里我们遇到了一个问题——第一种类型的 a 的类型是 Organism 而第二种类型是 Rank。没有既是 Organism 又是 Rank 的类型,所以编译失败。

注意:从报错信息可以看出,Elm实际上是在尝试将分支的类型与函数结果类型统一起来。 (我描述了另一个方向,因为我认为它更容易理解。)Elm 遵循的方向也失败了,因为它会递归并尝试统一具体的 Organism 类型和通用的 object 类型,类似地以及我们如何尝试统一两种具体类型。