functional-programming - 如何与 Elm 中的多态子组件通信?

标签 functional-programming polymorphism elm unification union-types

我的主程序有一个更新功能

update : Msg -> Model -> ( Model, Cmd Msg )

为了与子组件通信,我们可以添加另一个变体并将消息包装在新消息中

type alias Model =
    { ...
    , child : Child.Model
    }

type Msg
    = ...
    | ChildMsg Child.Msg

update msg model =
    case msg of
        ...

        ChildMsg childMsg ->
          let
              ( childModel, cmd ) =
                  Child.update childMsg model.child

              updatedModel =
                  { model | child = childModel }

              childCmd =
                Cmd.map ChildMsg cmd
          in
               ( updatedModel, childCmd )

但是,如果我的子组件的 update 函数的类型与父组件不匹配,这似乎具有挑战性。考虑一个具有多态更新函数的子进程:

-- PolymorphicChild.elm

update : Msg a -> Model -> ( Model, Cmd (Msg a) )

从此模块运行命令时,我必须将其包装

PolymorphicChild.someCommand : Cmd (Msg Foo)

PolymorphicChild.someCommand
  |> Cmd.map PolymorphicChild

但是,这会产生 Msg (PolymorphicChild.Msg Foo),而不是我的应用程序期望的 Msg PolymorphicChild.Msg

The right side of (|>) is causing a type mismatch.

(|>) is expecting the right side to be a:

    Cmd (PolyMorphicChild.Msg Foo) -> a

But the right side is:

    Cmd Polymorphic.Msg -> Cmd Msg

我尝试向 App.Msg 添加多态参数

-- App.elm

type Msg a =
   = ..
   | PolymorphicChildMsg (PolymorphicChild.Msg a) 

但这基本上毁掉了我的整个程序。每个涉及 App.Msg 的函数都需要以某种方式进行更改才能与新的子组件一起使用。

如何统一这两种类型并使这两个组件协同工作?

最佳答案

我认为问题在于您在公开的 Msg 类型中泄露了太多信息。您对 Msg a 类型参数的使用似乎仅限于一组已知的类型,例如 AuthorCategoryPost标签。从浏览你的代码来看,它看起来永远不会只是这四种之一,因此你以这种方式抽象事物的事实应该保留在这个模块内部,而不是暴露它并给可能拉动的任何其他代码带来负担。这个在。

我认为您需要将抽象降低一个级别,以避免参数化您的公共(public) Msg 类型。我建议为 Msg 使用四个具体的构造函数,而不是对其进行参数化,并将抽象转移到帮助器 LoadInfo a 类型:

type alias LoadInfo a =
    { worker : Worker a
    , url : Url
    , result : Result Http.Error ( Int, List a )
    }

type Msg
    = LoadPost (LoadInfo Post)
    | LoadCategory (LoadInfo Category)
    | LoadTag (LoadInfo Tag)
    | LoadAuthor (LoadInfo Author)

关于functional-programming - 如何与 Elm 中的多态子组件通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51199458/

相关文章:

scala:在函数(val)中定义默认参数与使用方法(def)

榆树,JSON 解码器 : How to decode an empty string?

elm - <~ 在 elm 0.16.0 中给我一个编译时错误

elm - 让单选按钮反射(reflect)模型

Haskell 元组构造函数 (GHC) 以及语言与其实现之间的分离

algorithm - 功能性 "All except one"

haskell - 我使用 randomRIO 错了吗?

rust - 这个理解对吗: trait and function overloading both achieved ad hoc polymorphism but in different direction

c++ - 使用构造函数参数实例化类对象和不带参数 C++ 的 * 运算符之间的区别

Objective-C 指向实现协议(protocol)的类的指针