Types elm中的类型继承

Types elm中的类型继承,types,elm,Types,Elm,我试图实现的是类型继承。我的意思是,我想让函数返回“子类型”,然后返回“超级类型”。让我给你举个例子 假设我有一个主视图组件,它返回一个Html消息 view: Model -> Html Msg view model = div [class "goal-box"] [ function_a model, function_b model ] 现在我希望function\u a和function\u b能够返回Msg function\u a

我试图实现的是类型继承。我的意思是,我想让函数返回“子类型”,然后返回“超级类型”。让我给你举个例子

假设我有一个主视图组件,它返回一个Html消息

view:  Model -> Html Msg
view model = 
    div [class "goal-box"] [
      function_a model,
      function_b model
    ]
现在我希望
function\u a
function\u b
能够返回
Msg

function\u a:Model->Html-AMsg

function\u b:Model->Html BMsg

我之所以要这样做,是因为我想确保函数_a在它可以生成何种消息方面受到限制,函数_b也是如此,但最终我需要一个使用这两者的统一视图

因此,将味精定义为

type Msg 
  = AMsg
  | BMsg

type AMsg
  = AnotherMsg Int
  | AgainMsg Int

type BMsg
  = ThisMsg String
  | ThatMsg Int
这似乎不起作用,因为编译器告诉我,它期望返回值的类型是
Html Msg
,而不是
Html AMsg

我希望这是清楚的。我觉得类型是我在JS中挣扎最多的概念,但希望我朝着正确的方向前进

免责声明


我在当天早些时候问过一个类似的问题,但我意识到我犯了一个错误,然后在编辑它的过程中困惑了好几次。所以我不得不删除它。提前向花时间阅读并回答的人道歉。

这里有两个主要问题

首先,您的
Msg
中的
AMsg
BMsg
不引用这些类型,它们只是您的
Msg
类型的构造函数

您需要将此更改为:

type Msg 
  = AMsg AMsg
  | BMsg BMsg
在这里,每行的第一个
AMsg
BMsg
Msg
类型的构造函数,第二个是其他类型的构造函数。在此之后,您可以创建类似于
AMsg(AnotherMsg 34)
的值

其次,您需要在
视图中使用function
Html.map
来更改消息类型,以便当
函数a
发送消息
AnotherMsg 34
(类型
AMsg
)时,该消息将转换为
AMsg(AnotherMsg 34)
(类型
Msg
)因此,在您的
视图中
所有消息的类型都相同

下面是完整的示例代码,下面是ellie示例:


我认为您正在尝试做的,以及您在上一个问题中尝试做的方式,非常有意义,并且是OCaml中称为多态变体的一个特性。不幸的是,Elm不支持它,这可能是因为这种东西有一些微妙的问题,使它不那么吸引人,特别是对于一门针对初学者的语言。@glennsl是的,我想这就是你在我的另一个问题中试图向我解释的。不幸的是,我的措辞是错误的,还有一些其他的错误使我相信继承是正确的。我想编辑这个问题,但它变得太混乱了,所以我决定删除并重新创建。无论如何,马库斯的回答似乎完成了任务,但我当然希望这是一个更直接的。这可能会发生在将来,我们只是在版本0.19毕竟谢谢!这确实感觉有点麻烦,但至少它完成了任务
module Main exposing (main)

import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)

type alias Model =
    {}

init : Model
init =
    {}

type Msg 
  = AMsg AMsg
  | BMsg BMsg

type AMsg
  = AnotherMsg Int
  | AgainMsg Int

type BMsg
  = ThisMsg String
  | ThatMsg Int

view : Model -> Html Msg
view model = 
    div [] [
      Html.map AMsg (function_a model),
      Html.map BMsg (function_b model)
    ]

function_a : Model -> Html AMsg
function_a model =
    div [] [ text "A" ]

function_b : Model -> Html BMsg
function_b model =
    div [] [ text "B" ]

update : Msg -> Model -> Model
update msg model =
    model

main : Program () Model Msg
main =
    Browser.sandbox
        { init = init
        , view = view
        , update = update
        }