如何在 Elm 中进行适当的继承?
How to do proper inheritance in Elm?
我正在制作一个可以包含类型 A 或类型 B 的项目的待办事项列表。所以我制作了一个类型 Item
,即 A
或 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
下面的函数用于通过使用 Id
.
查找来更新模型中的 ItemModel
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.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)
,但我希望它适用于 A
和 B
。我该如何解决这个问题?
-- 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
首先,最好使用 Dict
,而不是 List (Id, ItemModel)
。
然后只是模式匹配(代码未经测试):
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 }
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,尤其是有关标记联合的部分。
我正在制作一个可以包含类型 A 或类型 B 的项目的待办事项列表。所以我制作了一个类型 Item
,即 A
或 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
下面的函数用于通过使用 Id
.
ItemModel
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.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)
,但我希望它适用于 A
和 B
。我该如何解决这个问题?
-- 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
首先,最好使用 Dict
,而不是 List (Id, ItemModel)
。
然后只是模式匹配(代码未经测试):
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 }
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,尤其是有关标记联合的部分。