在 Elm 中,有没有办法合并联合类型? (出于模块化目的)

In Elm, is there a way to merge union types ? (for modularity purpose)

从这三个声明开始:

type SharedMsg
   = SharedAction

type Page1Msg
   = Page1Action

type Page2Msg
   = Page2Action

我有办法得到下面的一个等价物吗?喜欢 "merge" 联合类型的方法吗?

type Msg
   = SharedAction
   | Page1Action
   | Page2Action

===============================

上下文:我将一个 Elm 应用程序拆分为一个模块,每个页面都有自己的文件夹。

一些操作将被共享,而一些操作将特定于页面。

如果我要使用 Html.map 方法,我觉得我必须重写页面在其自己的 PageMsg 消息类型中使用的每个共享操作:

type Page1Msg
   = Page1Action
   | SharedAction

type Msg
   = Page1Msg Page1Msg
   | Page2Msg Page2Msg

view : Model -> Html Msg
view =
   Html.map Page1Msg (Page1View.view model)

因此,我想为所有页面使用唯一的 Msg 类型,但通过在它们自己的文件夹中编写特定于页面的消息来保持模块化,然后通过合并以某种方式定义唯一的 Msg 类型他们。

问题是,你说过:

type SharedMsg
   = SharedAction

所以我们知道 SharedAction 的类型是 SharedMsg
但是你说:

type Msg
   = SharedAction
   | Page1Action
   | Page2Action

所以现在矛盾了,因为 SharedActionMsg

解决这个问题的简单方法是:

type Msg
   = Msg SharedMsg
   | Msg Page1Msg
   | Msg Page2Msg

Msg 是一个构造函数,其实例类型为 Msg,可以具有以下值。

请记住,您绝对没有义务完全按照基本示例中的 update-view 定义进行操作。在您的情况下,您可以根据需要调整更新功能

parent怎么样:

update message model = 
    let 
        sharedMsgs = 
            { msg1 = Msg1 
            , msg2 = Msg2 
            }

    in case message of
        Page1Msg msg ->
            let (m, c) =
                update sharedMsgs msg model.page1
            in case c of 
                Nothing ->
                    m 
                Just c ->
                    update c m

page1 中的更新函数有签名

update : SharedMessages msg -> Msg -> Page1Model -> (Page1Model, Maybe msg)

@z5h 的回答几乎是正确的,但是类型构造函数必须有不同的名称。

您不能按照自己喜欢的方式合并类型。

至于惯用的方式:您可以将拆分类型命名为 Msg,而不是 Page1Msg。所以,例如:

Page1.elm:

module Page1 exposing (Msg)

type Msg
  = Foo

Page2.elm:

module Page2 exposing (Msg)

type Msg
  = Bar

Shared.elm:

module Shared exposing (Msg)

type Msg
  = Baz

Main.elm:

module Main exposing (..)

import Shared
import Page1
import Page2

type Msg
  = SomethingCustom
  | SharedMsg Shared.Msg
  | Page1Msg Page1.Msg
  | Page2Msg Page2.Msg

对了,记得如果把模块拆分成Page1.ViewPage1.Types等,那么只要暴露的功能不重叠,就可以在下面引入不同的模块同名,即:

import Page1.Types as Page1
import Page1.State as Page1
import Page1.View as Page1
import Page1.Decoders as Page1