榆树:更新子类型的值

时间:2017-12-07 16:08:13

标签: elm

我有这种类型

type alias Cat =
 { head : Head
 }

type alias Head =
  { eyes : Int
  , nose : Int
  , mouth : Mouth
  }

type alias Mouth =
  { tongue : Int
  , prey : Prey
  }

type alias Prey =
  { left : Int
  , right : Int 
  }

插入值

cat : Cat
cat = 
  { head = 
    { eyes = 2
    , nose = 1
    , mouth = 
      { tongue = 1
      , prey = 
        { left = 1
        , right = 1
        }
      }
    }
  }

我通常这样做是为了改变猎物的右侧

let  
  newCat = 
    (Cat 
      (Head oldValue.eyes oldValue.nose 
        (Mouth 
          (Prey oldValue.left 1)
        )
      )
    )
in
 ({model | cat = newCat }, Cmd.none)

我讨厌这样做,但我无法弄清楚如何以正确的方式做到这一点。当我尝试做正确的时候,我无法返回'输入cat'。

如何以正确的方式改变正确的猎物?

1 个答案:

答案 0 :(得分:5)

你已经以正确的方式做到了。

当你处理嵌套记录时,你必须建立它们,就像你已经在做的那样。

现在,您可以做的是抽象newCat并将其转换为Int -> Cat -> Cat类型的函数。然后,您就可以({model | cat = updateRightPrey 1 model.cat }, Cmd.none)

但老实说,您可能想重新考虑您的数据模型。 HeadMouthPrey实际上是否提供了任何价值?如果你像这样压扁你的模型,你会放松什么(以及你必须获得什么):

type alias Cat = 
  { eyes : Eyes
  , nose : Nose
  , tongue : Tongue
  , left : Prey
  , right : Prey 
  }

type alias Eyes = Int
type alias Nose = Int
type alias Tongue = Int
type alias Prey = Int

即使您将所有Int类型别名更改为类型...

type Eyes = Eyes Int

...它比处理嵌套记录简单得多:

let
    cat = model.cat
in
({model | cat = { cat | right = 1 }, Cmd.none)

...或

let
    cat = model.cat
in
({model | cat = { cat | right = Prey 1 }, Cmd.none)