在 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
所以现在矛盾了,因为 SharedAction
是 Msg
。
解决这个问题的简单方法是:
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.View
、Page1.Types
等,那么只要暴露的功能不重叠,就可以在下面引入不同的模块同名,即:
import Page1.Types as Page1
import Page1.State as Page1
import Page1.View as Page1
import Page1.Decoders as Page1
从这三个声明开始:
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
所以现在矛盾了,因为 SharedAction
是 Msg
。
解决这个问题的简单方法是:
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.View
、Page1.Types
等,那么只要暴露的功能不重叠,就可以在下面引入不同的模块同名,即:
import Page1.Types as Page1
import Page1.State as Page1
import Page1.View as Page1
import Page1.Decoders as Page1