我想要实现的是类型继承.我的意思是我希望能够让函数返回"子类型",然后返回一个返回"超类型"的函数.让我给你举个例子
假设我有一个主视图组件,它返回一个Html消息
view: Model -> Html Msg
view model =
div [class "goal-box"] [
function_a model,
function_b model
]
Run Code Online (Sandbox Code Playgroud)
现在我想function_a和function_b每个人都能够返回一个子类型Msg
function_a: Model -> Html AMsg
function_b: Model -> Html BMsg
我想要这个的原因是因为我想确保function_a受限于它可以产生什么样的Msg,同样适用于function_b,但最终我需要一个使用两者的统一视图.
所以很自然的是将Msg定义为
type Msg
= AMsg
| BMsg
type AMsg
= AnotherMsg Int
| AgainMsg Int
type BMsg
= ThisMsg String
| ThatMsg Int
Run Code Online (Sandbox Code Playgroud)
这似乎不起作用,因为编译器告诉我它期望返回值类型Html Msg而不是Html AMsg.
我希望这很清楚.我觉得类型是我正在努力争取最多来自JS的概念,但希望我朝着正确的方向前进.
免责声明
我在当天早些时候问了一个类似的问题,但我意识到我犯了一个错误,然后在我编辑它时混淆了几次.所以我不得不删除它.向花时间阅读和回答的人们道歉.
这里有两个主要问题.
首先AMsg,BMsg在您Msg不参考这些类型的情况下,它们只是您的Msg类型的构造函数.
您需要将其更改为:
type Msg
= AMsg AMsg
| BMsg BMsg
Run Code Online (Sandbox Code Playgroud)
这里第一行AMsg和第一BMsg行是Msg类型的构造函数,第二行是指其他类型.在此之后,你可以创建像这样的值AMsg (AnotherMsg 34).
其次,你需要使用的功能Html.map在view改变消息类型,这样,当如function_a发送消息AnotherMsg 34(类型的AMsg),将被改造成AMsg (AnotherMsg 34)(类型Msg,并在你的),所以view所有的消息都是同一类型的.
以下是完整的示例代码,其中有ellie示例:https://ellie-app.com/3TG62zDLvwFa1
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
}
Run Code Online (Sandbox Code Playgroud)