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

问题描述 投票:1回答:1

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

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

但是榆树不允许它为每个案例表达说

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?

所以我的问题是:如何从ModelFields获得Model?还是我做了一些从根本上有缺陷的事情?

UPD。我正在尝试建模的细节。

我有Organism类型的对象。他们被分为Ranks。我的服务器对Organisms进行了一些成对分析,例如。计算两个Similaritys之间的DistanceOrganism。我想在不同页面的两个表格中显示这些分析的结果,一页用于Similarity分析,一页用于Distance分析。这意味着该表应该可以重复使用以接受任何形式的分析结果。另一方面,这些表有一种常见的模式。他们可以处于两种状态:

  1. 显示endValues之间成对比较(ModelOrganism)的具体结果,因此表格的行和列代表Organisms。
  2. 显示statss组(Models)之间的统计值(例如,Rank中的平均值或标准偏差,Organism),在这种情况下,表格的行和列代表Ranks。

显示哪个Ranks或Organisms取决于locationModelFields字段。用户可以单击一个按钮,我想在我的location函数中更改update。这种导航变化可能会在ShowEndValuesShowStatistics状态之间切换。这就是我试图从ModelFields构造函数中解开Model的原因。我附上一个简单的插图,希望它有助于澄清.table illustration

types elm algebraic-data-types unification parametric-polymorphism
1个回答
1
投票

这确实是不可能的。

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

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

注意:正如您从错误消息中看到的,Elm实际上尝试使用函数结果类型统一分支的类型。 (我描述了另一个方向,因为我认为更清楚地理解。)Elm所遵循的方向也失败了,因为它会递归并试图统一具有通用Organism类型的具体object类型,类似于我们如何尝试统一两个混凝土类型。

© www.soinside.com 2019 - 2024. All rights reserved.