Elm允许循环引用吗?

Elm允许循环引用吗?,elm,Elm,假设有两种数据类型: type alias Player = { name : String , team : Team } type alias Team = { name : String , players : List Player } 这个JSON: { "players": [ { "id": 100, "name": "Sam Bradford", "teamId": 200 }, { "id": 101, "name": "Kyl

假设有两种数据类型:

type alias Player = 
  { name : String
  , team : Team
  }

type alias Team =
  { name : String
  , players : List Player
  }
这个JSON:

{
  "players": [
    { "id": 100, "name": "Sam Bradford", "teamId": 200 },
    { "id": 101, "name": "Kyle Rudolph", "teamId": 200 },
    { "id": 102, "name": "Matthew Stafford", "teamId": 201 },
    { "id": 103, "name": "Marvin Jones Jr.", "teamId": 201 },
    { "id": 104, "name": "Golden Tate", "teamId": 201 },
  ],
  "teams": [
    { "id": 200, "name": "Minnesota Vikings" },
    { "id": 201, "name": "Detroit Lions" },
  ]
}

很明显,这个JSON可以被解码成非空链接对象,这可以由JSON解码器在解码数据时确定。有没有办法解码这个JSON并创建链接的数据结构?我不知道如何使用完全不可变的数据结构,或者如果可能的话。使用不可变的数据结构,不可能创建以某种循环方式相互引用的完全耦合的值层次结构

问题的核心可以通过几个步骤来说明:

  • 为其父字段创建一个子字段,其中不包含任何内容
  • 创建指向子对象的父对象
  • 更新子对象以指向父对象
  • 当您拥有不可变的数据结构时,第3项是不可能的,因为对子项的“修改”意味着您创建了一个新值,而父项仍将指向该旧值。如果您随后更新了父对象,那么您必须再次无限地更新子对象


    我建议使用球员和球队的
    Dict
    ,根据各自的ID进行索引,以便于查找。

    Elm中的递归数据类型有一个很好的解释

    如果尝试编译数据类型,则会出现以下错误:

    -- ALIAS PROBLEM ---------------------------------------------------------------
    
    This type alias is part of a mutually recursive set of type aliases.
    
    4|>type alias Player = 
    5|>  { name : String
    6|>  , team : Team
    7|>  }
    
    The following type aliases are mutually recursive:
    
        ┌─────┐
        │     V
        │    Player
        │     │
        │     V
        │    Team
        └─────┘
    
    You need to convert at least one `type alias` into a `type`. This is a kind of
    subtle distinction, so definitely read up on this before you make a fix:
    <https://github.com/elm-lang/elm-compiler/blob/0.17.0/hints/recursive-alias.md>
    
    更新:您在问题中还提到了
    null
    引用。在上面的数据类型中,每个玩家必须有一个团队。如果团队是可选字段,我将定义如下:

    type alias Player = 
      { name : String
      , teamID : Maybe ID
      }
    
    对于
    列表
    字符串
    类型,实际上不需要
    可能
    类型。使用
    []
    (空列表)和
    (空字符串)可以更轻松地为这些对象设置空状态

    PS:另一个假设是,您需要在模型的每个团队中存储团队成员列表。因为严格来说你不需要:球员名单已经有了确定哪些球员(如果有的话)属于X队所需的所有数据。
    请注意,如果您维护双向参考,需要做大量工作(并可能导致严重的错误):如果一名球员更换球队,您需要更新3条记录(1名球员+2名球队记录)。

    如果您真的想要一个如您所述的结构,球队和球员可以在浅层上相互参考,它可以通过一些
    Json实现。然后是
    acrobatic。我很好奇,所以我继续写了一个快速而肮脏的例子来说明如何做到这一点。顺便说一句:@ChadGilbert在回答中也提到了用
    Dict
    ID
    处理循环引用。
    type alias Player = 
      { name : String
      , teamID : Maybe ID
      }