如何在榆树中进行适当的遗传?

时间:2015-12-07 16:46:11

标签: inheritance functional-programming elm

我正在创建一个可以包含类型A或类型B的项目的待办事项列表。所以我创建了ItemA类型B。该模型包含ItemModel列表和一个整数,我们用它来为每个待办事项分配一个id。

module Feed where

import A
import B

-- MODEL

type Item = A | B
type ItemModel = A.Model | B.Model

type alias Id = Int

type alias Model = 
    { todo : List (Id, ItemModel)
    , nextCount : Id}

init : Model
init = Model [] 0

以下功能用于通过使用ItemModel进行查找来更新模型中的Id

updateItem : (ItemModel -> ItemModel) -> Id -> Model -> Model
updateItem f id model =
  let test (id', x) = (id', if id == id' then f x else x)
  in Model (List.map test model.todo) model.nextCount 

麻烦从这里开始。我不知道如何使用已调用操作的Item的更新功能。 Item.update不起作用,因为它不存在。

-- UPDATE

type Action = SubAction Id Item.Action

update : Action -> Model -> Model
update action model =
  case action of
    SubAction id action ->
      updateItem (Item.update action) id model

我也无法显示我的列表,我知道Item.view不起作用,但这是为了说明我的想法。如果f.e.代码有效。我使用A.view并拥有todo : List (Id, A.Model),但我希望它适用于AB。我该如何解决这个问题?

-- VIEW

view : Signal.Address Action -> Model -> Html
view address model =
  let view' (id, x) = Item.view (Signal.forwardTo address <| SubAction id) x
      lstTodo = List.map view' model.todo
  in Html.div [] lstTodo

1 个答案:

答案 0 :(得分:3)

首先,而不是List (Id, ItemModel)更好地使用Dict

然后只是模式匹配(代码未经测试):

type Item = ItemA A.Model | ItemB B.Model
type Action = SubActionA Id A.Action | SubActionB Id B.Action | ...

updateA : A.Action -> Item -> Item
updateA action model = case model of
  ItemA model -> ... -- we have an A item here, do something
  Nothing -> ... -- there's a B item here, app logic must be wrong somewhere

updateB : B.Action -> Item -> Item
updateB action model = case model of
  ItemB model -> ... -- we have a B item here, do something
  Nothing -> ... -- there's an A item here, app logic must be wrong somewhere

update : Action -> Model -> Model
update action model =
  case action of
    SubActionA id action -> { model | todo = Dict.update id (Maybe.map (updateA action)) model.todo }
    SubActionB id action -> { model | todo = Dict.update id (Maybe.map (updateB action)) model.todo }
这里有{p> updateA/B action - 因此类型为ItemModel -> ItemModel

另请注意,Maybe.map会将函数a -> b映射到Maybe a -> Maybe b - 正是Dict.update所期望的!

同样在视图中:

case model of
  ItemA model -> A.view model
  ItemB model -> B.view model

如需进一步参考 - 请阅读this,尤其是有关已标记联盟的部分。