Type inheritance in elm
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
add a comment |
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
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
add a comment |
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
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
types elm
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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
Thanks! It definitely feels a bit cumbersome, but at least it gets the job done
– Nicola Pedretti
Nov 16 '18 at 14:27
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
Thanks! It definitely feels a bit cumbersome, but at least it gets the job done
– Nicola Pedretti
Nov 16 '18 at 14:27
add a comment |
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
Thanks! It definitely feels a bit cumbersome, but at least it gets the job done
– Nicola Pedretti
Nov 16 '18 at 14:27
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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