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

时间:2017-05-11 10:13:07

标签: elm modularity union-types

从这三个声明开始:

type SharedMsg
   = SharedAction

type Page1Msg
   = Page1Action

type Page2Msg
   = Page2Action

我有办法获得相同的以下一个吗?就像一种“合并”联合类型的方式?

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类型。

3 个答案:

答案 0 :(得分:5)

@ 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

答案 1 :(得分:2)

不要忘记,您绝对没有义务完全按照基本示例中的更新视图定义。在您的情况下,您可以根据需要调整更新功能

在父母身上怎么样:

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)

答案 2 :(得分:0)

问题是,你说过:

type SharedMsg
   = SharedAction

因此我们知道SharedAction的类型是SharedMsg 但是你说:

type Msg
   = SharedAction
   | Page1Action
   | Page2Action

现在是一个矛盾,因为SharedActionMsg

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

type Msg
   = Msg SharedMsg
   | Msg Page1Msg
   | Msg Page2Msg

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