Type inheritance in elm










4















What I am trying to achieve is type inheritance. What I mean by that is that I want to be able to have functions returning "sub-types" and then a function returning the "super-type". Let me give you an example



let's say I have a main View component which returns an Html Msg



view: Model -> Html Msg
view model =
div [class "goal-box"] [
function_a model,
function_b model
]


Now I would like function_a and function_b to each be able to return a subtype of Msg



function_a: Model -> Html AMsg



function_b: Model -> Html BMsg



The reason why I want this is because I want to make sure function_a is limited in what kind of Msg it can produce, and same goes for function_b, but eventually I need a unified view that uses both.



So what came natural was to define Msg as



type Msg 
= AMsg
| BMsg

type AMsg
= AnotherMsg Int
| AgainMsg Int

type BMsg
= ThisMsg String
| ThatMsg Int


This does not seem to work, as the compiler tells me that it was expecting a return value of type Html Msg and not Html AMsg.



I hope this is clear. I feel like types are the concept I am struggling with the most coming from JS, but hopefully I am headed in the right direction.



DISCLAIMER



I have asked a similar question earlier in the day but I realized I made a mistake and then confused myself a couple of times as I was editing it. So I had to delete it. Apologies in advance to the people that took the time to read it and answer.










share|improve this question






















  • I think what you're trying to do, and the way you tried to do it in the previous question, makes perfect sense and is a feature in OCaml called polymorphic variants. Unfortunately Elm doesn't support it, and that might be because there's some subtle issues with this kind of thing that makes it less appealing, especially for a language aimed at beginners.

    – glennsl
    Nov 16 '18 at 9:25






  • 1





    @glennsl yeah, I think that’s what you were trying to explain to me in my other question. Unfortunately I phrased it wrong and I had a couple of other errors that made me believe inheritance was working correctly. I thought about editing the question but it was getting too confusing so I decided to just delete and recreate. Anyhow, Markus answer seems to get the job done, but I certainly wish this was a bit more straight forward. It might happen in the future, we are only at version 0.19 after all

    – Nicola Pedretti
    Nov 16 '18 at 14:31















4















What I am trying to achieve is type inheritance. What I mean by that is that I want to be able to have functions returning "sub-types" and then a function returning the "super-type". Let me give you an example



let's say I have a main View component which returns an Html Msg



view: Model -> Html Msg
view model =
div [class "goal-box"] [
function_a model,
function_b model
]


Now I would like function_a and function_b to each be able to return a subtype of Msg



function_a: Model -> Html AMsg



function_b: Model -> Html BMsg



The reason why I want this is because I want to make sure function_a is limited in what kind of Msg it can produce, and same goes for function_b, but eventually I need a unified view that uses both.



So what came natural was to define Msg as



type Msg 
= AMsg
| BMsg

type AMsg
= AnotherMsg Int
| AgainMsg Int

type BMsg
= ThisMsg String
| ThatMsg Int


This does not seem to work, as the compiler tells me that it was expecting a return value of type Html Msg and not Html AMsg.



I hope this is clear. I feel like types are the concept I am struggling with the most coming from JS, but hopefully I am headed in the right direction.



DISCLAIMER



I have asked a similar question earlier in the day but I realized I made a mistake and then confused myself a couple of times as I was editing it. So I had to delete it. Apologies in advance to the people that took the time to read it and answer.










share|improve this question






















  • I think what you're trying to do, and the way you tried to do it in the previous question, makes perfect sense and is a feature in OCaml called polymorphic variants. Unfortunately Elm doesn't support it, and that might be because there's some subtle issues with this kind of thing that makes it less appealing, especially for a language aimed at beginners.

    – glennsl
    Nov 16 '18 at 9:25






  • 1





    @glennsl yeah, I think that’s what you were trying to explain to me in my other question. Unfortunately I phrased it wrong and I had a couple of other errors that made me believe inheritance was working correctly. I thought about editing the question but it was getting too confusing so I decided to just delete and recreate. Anyhow, Markus answer seems to get the job done, but I certainly wish this was a bit more straight forward. It might happen in the future, we are only at version 0.19 after all

    – Nicola Pedretti
    Nov 16 '18 at 14:31













4












4








4


1






What I am trying to achieve is type inheritance. What I mean by that is that I want to be able to have functions returning "sub-types" and then a function returning the "super-type". Let me give you an example



let's say I have a main View component which returns an Html Msg



view: Model -> Html Msg
view model =
div [class "goal-box"] [
function_a model,
function_b model
]


Now I would like function_a and function_b to each be able to return a subtype of Msg



function_a: Model -> Html AMsg



function_b: Model -> Html BMsg



The reason why I want this is because I want to make sure function_a is limited in what kind of Msg it can produce, and same goes for function_b, but eventually I need a unified view that uses both.



So what came natural was to define Msg as



type Msg 
= AMsg
| BMsg

type AMsg
= AnotherMsg Int
| AgainMsg Int

type BMsg
= ThisMsg String
| ThatMsg Int


This does not seem to work, as the compiler tells me that it was expecting a return value of type Html Msg and not Html AMsg.



I hope this is clear. I feel like types are the concept I am struggling with the most coming from JS, but hopefully I am headed in the right direction.



DISCLAIMER



I have asked a similar question earlier in the day but I realized I made a mistake and then confused myself a couple of times as I was editing it. So I had to delete it. Apologies in advance to the people that took the time to read it and answer.










share|improve this question














What I am trying to achieve is type inheritance. What I mean by that is that I want to be able to have functions returning "sub-types" and then a function returning the "super-type". Let me give you an example



let's say I have a main View component which returns an Html Msg



view: Model -> Html Msg
view model =
div [class "goal-box"] [
function_a model,
function_b model
]


Now I would like function_a and function_b to each be able to return a subtype of Msg



function_a: Model -> Html AMsg



function_b: Model -> Html BMsg



The reason why I want this is because I want to make sure function_a is limited in what kind of Msg it can produce, and same goes for function_b, but eventually I need a unified view that uses both.



So what came natural was to define Msg as



type Msg 
= AMsg
| BMsg

type AMsg
= AnotherMsg Int
| AgainMsg Int

type BMsg
= ThisMsg String
| ThatMsg Int


This does not seem to work, as the compiler tells me that it was expecting a return value of type Html Msg and not Html AMsg.



I hope this is clear. I feel like types are the concept I am struggling with the most coming from JS, but hopefully I am headed in the right direction.



DISCLAIMER



I have asked a similar question earlier in the day but I realized I made a mistake and then confused myself a couple of times as I was editing it. So I had to delete it. Apologies in advance to the people that took the time to read it and answer.







types elm






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 16 '18 at 1:09









Nicola PedrettiNicola Pedretti

2,05411825




2,05411825












  • I think what you're trying to do, and the way you tried to do it in the previous question, makes perfect sense and is a feature in OCaml called polymorphic variants. Unfortunately Elm doesn't support it, and that might be because there's some subtle issues with this kind of thing that makes it less appealing, especially for a language aimed at beginners.

    – glennsl
    Nov 16 '18 at 9:25






  • 1





    @glennsl yeah, I think that’s what you were trying to explain to me in my other question. Unfortunately I phrased it wrong and I had a couple of other errors that made me believe inheritance was working correctly. I thought about editing the question but it was getting too confusing so I decided to just delete and recreate. Anyhow, Markus answer seems to get the job done, but I certainly wish this was a bit more straight forward. It might happen in the future, we are only at version 0.19 after all

    – Nicola Pedretti
    Nov 16 '18 at 14:31

















  • I think what you're trying to do, and the way you tried to do it in the previous question, makes perfect sense and is a feature in OCaml called polymorphic variants. Unfortunately Elm doesn't support it, and that might be because there's some subtle issues with this kind of thing that makes it less appealing, especially for a language aimed at beginners.

    – glennsl
    Nov 16 '18 at 9:25






  • 1





    @glennsl yeah, I think that’s what you were trying to explain to me in my other question. Unfortunately I phrased it wrong and I had a couple of other errors that made me believe inheritance was working correctly. I thought about editing the question but it was getting too confusing so I decided to just delete and recreate. Anyhow, Markus answer seems to get the job done, but I certainly wish this was a bit more straight forward. It might happen in the future, we are only at version 0.19 after all

    – Nicola Pedretti
    Nov 16 '18 at 14:31
















I think what you're trying to do, and the way you tried to do it in the previous question, makes perfect sense and is a feature in OCaml called polymorphic variants. Unfortunately Elm doesn't support it, and that might be because there's some subtle issues with this kind of thing that makes it less appealing, especially for a language aimed at beginners.

– glennsl
Nov 16 '18 at 9:25





I think what you're trying to do, and the way you tried to do it in the previous question, makes perfect sense and is a feature in OCaml called polymorphic variants. Unfortunately Elm doesn't support it, and that might be because there's some subtle issues with this kind of thing that makes it less appealing, especially for a language aimed at beginners.

– glennsl
Nov 16 '18 at 9:25




1




1





@glennsl yeah, I think that’s what you were trying to explain to me in my other question. Unfortunately I phrased it wrong and I had a couple of other errors that made me believe inheritance was working correctly. I thought about editing the question but it was getting too confusing so I decided to just delete and recreate. Anyhow, Markus answer seems to get the job done, but I certainly wish this was a bit more straight forward. It might happen in the future, we are only at version 0.19 after all

– Nicola Pedretti
Nov 16 '18 at 14:31





@glennsl yeah, I think that’s what you were trying to explain to me in my other question. Unfortunately I phrased it wrong and I had a couple of other errors that made me believe inheritance was working correctly. I thought about editing the question but it was getting too confusing so I decided to just delete and recreate. Anyhow, Markus answer seems to get the job done, but I certainly wish this was a bit more straight forward. It might happen in the future, we are only at version 0.19 after all

– Nicola Pedretti
Nov 16 '18 at 14:31












1 Answer
1






active

oldest

votes


















6














There are two main issues here.



Firstly AMsg and BMsg in your Msg do not refer to those types, they are just constructors for your Msg type.



You need to change this to:



type Msg 
= AMsg AMsg
| BMsg BMsg


Here first AMsg and BMsg on each line are constructors for Msg type, and second ones refer to your other types. After this you can create values like AMsg (AnotherMsg 34).



Secondly you need to use function Html.map in your view to change message types so that when e.g. function_a sends message AnotherMsg 34 (of type AMsg), that will be transformed into AMsg (AnotherMsg 34) (of type Msg) and so in your view all messages are of same type.



Full example code below, with ellie example here: 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






share|improve this answer























  • Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

    – Nicola Pedretti
    Nov 16 '18 at 14:27










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53330051%2ftype-inheritance-in-elm%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









6














There are two main issues here.



Firstly AMsg and BMsg in your Msg do not refer to those types, they are just constructors for your Msg type.



You need to change this to:



type Msg 
= AMsg AMsg
| BMsg BMsg


Here first AMsg and BMsg on each line are constructors for Msg type, and second ones refer to your other types. After this you can create values like AMsg (AnotherMsg 34).



Secondly you need to use function Html.map in your view to change message types so that when e.g. function_a sends message AnotherMsg 34 (of type AMsg), that will be transformed into AMsg (AnotherMsg 34) (of type Msg) and so in your view all messages are of same type.



Full example code below, with ellie example here: 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






share|improve this answer























  • Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

    – Nicola Pedretti
    Nov 16 '18 at 14:27















6














There are two main issues here.



Firstly AMsg and BMsg in your Msg do not refer to those types, they are just constructors for your Msg type.



You need to change this to:



type Msg 
= AMsg AMsg
| BMsg BMsg


Here first AMsg and BMsg on each line are constructors for Msg type, and second ones refer to your other types. After this you can create values like AMsg (AnotherMsg 34).



Secondly you need to use function Html.map in your view to change message types so that when e.g. function_a sends message AnotherMsg 34 (of type AMsg), that will be transformed into AMsg (AnotherMsg 34) (of type Msg) and so in your view all messages are of same type.



Full example code below, with ellie example here: 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






share|improve this answer























  • Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

    – Nicola Pedretti
    Nov 16 '18 at 14:27













6












6








6







There are two main issues here.



Firstly AMsg and BMsg in your Msg do not refer to those types, they are just constructors for your Msg type.



You need to change this to:



type Msg 
= AMsg AMsg
| BMsg BMsg


Here first AMsg and BMsg on each line are constructors for Msg type, and second ones refer to your other types. After this you can create values like AMsg (AnotherMsg 34).



Secondly you need to use function Html.map in your view to change message types so that when e.g. function_a sends message AnotherMsg 34 (of type AMsg), that will be transformed into AMsg (AnotherMsg 34) (of type Msg) and so in your view all messages are of same type.



Full example code below, with ellie example here: 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






share|improve this answer













There are two main issues here.



Firstly AMsg and BMsg in your Msg do not refer to those types, they are just constructors for your Msg type.



You need to change this to:



type Msg 
= AMsg AMsg
| BMsg BMsg


Here first AMsg and BMsg on each line are constructors for Msg type, and second ones refer to your other types. After this you can create values like AMsg (AnotherMsg 34).



Secondly you need to use function Html.map in your view to change message types so that when e.g. function_a sends message AnotherMsg 34 (of type AMsg), that will be transformed into AMsg (AnotherMsg 34) (of type Msg) and so in your view all messages are of same type.



Full example code below, with ellie example here: 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







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 16 '18 at 2:04









Markus LaireMarkus Laire

1,9171120




1,9171120












  • Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

    – Nicola Pedretti
    Nov 16 '18 at 14:27

















  • Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

    – Nicola Pedretti
    Nov 16 '18 at 14:27
















Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

– Nicola Pedretti
Nov 16 '18 at 14:27





Thanks! It definitely feels a bit cumbersome, but at least it gets the job done

– Nicola Pedretti
Nov 16 '18 at 14:27



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53330051%2ftype-inheritance-in-elm%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Top Tejano songwriter Luis Silva dead of heart attack at 64

ReactJS Fetched API data displays live - need Data displayed static

政党