Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elm Reactor should pass flags: null #2251

Open
juliusl opened this issue Apr 6, 2022 · 3 comments
Open

Elm Reactor should pass flags: null #2251

juliusl opened this issue Apr 6, 2022 · 3 comments

Comments

@juliusl
Copy link

juliusl commented Apr 6, 2022

Quick Summary: To develop apps with JS-Interop it would be great if reactor would set init to null, so that on the Elm side you can declare main like main: Program (Maybe <some-type>) Model Msg.

Currently it doesn't set any value which means that undefined is returned, and this error will be shown

(1) Problem with the given value:
    
    undefined
    
    Expecting null

SSCCE

Try this in playground --

import Html exposing (text)
import Browser

main: Program (Maybe Int) Model Msg
main =
    Browser.document 
      { init = \a -> ({}, Cmd.none)
      , view = \m -> { title = "t", body = [text "hi"]}
      , update = \_ _ -> ({}, Cmd.none)
      , subscriptions = \_ -> Sub.none
      }

type alias Model = {}
type Msg = None

On a side note, I sort of expected to be able to do this:

type alias Undefined = () 

type Startup = Undefined | Maybe Int

main : Program Startup Model Msg 

But that results in:

BAD FLAGS - Your `main` program wants a `Startup` value from JavaScript.

21| main = 
    #^^^^#
I cannot handle that. The types that CAN be in flags include:

    Ints, Floats, Bools, Strings, Maybes, Lists, Arrays, tuples, records, and
    JSON values.

Since JSON values can flow through, you can use JSON encoders and decoders to
allow other types through as well. More advanced users often just do everything
with encoders and decoders for more control and better errors.

Which is reasonable, but seems a bit inconsistent when () compiles with Program () Model Msg.

@github-actions
Copy link

github-actions bot commented Apr 6, 2022

Thanks for reporting this! To set expectations:

  • Issues are reviewed in batches, so it can take some time to get a response.
  • Ask questions in a community forum. You will get an answer quicker that way!
  • If you experience something similar, open a new issue. We like duplicates.

Finally, please be patient with the core team. They are trying their best with limited resources.

@adamdicarlo
Copy link

type alias Undefined = ()

type Startup = Undefined | Maybe Int

type alias Undefined = () has no effect on the Startup declaration. Startup happens to have a type constructor called Undefined (which takes no parameters). The type alias Undefined is not referenced anywhere and can be removed without changing anything.

Similarly, Maybe is declared as a type constructor for Startup in this example, and it takes an Int parameter - it happens to be called Maybe but it does not use Elm's built in Maybe type.

type in Elm works a lot differently than in TypeScript - basically it's for creating "tagged union" types (unlike with TS, you don't need to have an object with a special "determinant" field). Each option for the type (the first word) is your own custom type constructor function, while following words are types. For example:

type = Fruit String | Vegetable String | Other

means you can declare variables like this

apple = Fruit "Apple"
broccoli = Vegetable "Broccoli"
wheat = Other

If it was possible to have a fruit with no name, you could do:

type = Fruit (Maybe String) | Vegetable String | Other

apple = Fruit (Just "Apple")
secretFruit = Fruit Nothing
broccoli = Vegetable "Broccoli"
wheat = Other

This is how you'd use an Elm Maybe in a custom type.

For flags, you need to do something a bit more involved in order to accept data with different shapes... I'm not super knowledgeable with the different techniques for decoding flags so I'll stop here and just drop the Elm guide's link on them for convenience: https://guide.elm-lang.org/interop/flags.html

Hope this helps!

@juliusl
Copy link
Author

juliusl commented Nov 11, 2022

@adamdicarlo Thanks for replying. That makes sense. Let me rephrase my example so I can get some clarity.

What is this type known as, () ?

And if I rewrite my example, then would this expression make sense,

type Startup = NoFlags () | Edit (Maybe Int) 

So what I'm looking for is the ability to do this,

type Startup = NoFlags () | IntFlag (Maybe Int) 

main: Program Startup Model Msg
...

The reason is because this is valid,

main: Program () Model Msg

and this is valid,

main: Program (Maybe Int) Model Msg

But the reason the second example wouldn't work in the playground is because the playground doesn't pass in null as a flag parameter, and by extension the reactor does not pass null as well. But if you were to write the html on your own and pass null it would work. But if you don't pass anything (undefined), then () is expected.

So I guess the limitation here is that main (elm compiler) doesn't accept union-types as a flag parameter?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants