Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of `Cmd msg`?

I'm trying to use ports to pass an URL to Javascript in order to redirect the user to another page. I wrote a port module to contain all the ports needed for my project :

port module Utils exposing (..)
port changePage : String -> Cmd Event

Then, I imported it in my Elm file :

type Event = PageChange String
import Utils exposing (changePage)

But the compiler didn't like it :

It looks like the keyword `import` is being used as a variable.
8| import Utils exposing (changePage)
         ^
Rename it to something else.

So I moved the port definition to the main file :

type Event = PageChange String
port changePage : String -> Cmd Event

But the compiler still didn't agree :

Port `changePage` has an invalid type.
28| port changePage : String -> Cmd Event
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You are saying it should be:
 String -> Platform.Cmd.Cmd BmC.Index.Event
But you need to use the particular format described here:
<http://guide.elm-lang.org/interop/javascript.html#ports>

So I went to see that particular format, port check : String -> Cmd msg. I didn't understand where that msg came from, so I went to check the code, and I still don't understand what that line means.

Where does msg come from? What does type Cmd msg = Cmd mean? Thanks in advance.

like image 422
Algorythmis Avatar asked Dec 03 '22 23:12

Algorythmis


2 Answers

import statements have to come before any function or type definitions. That's the reason you got a compile error on this code:

type Event = PageChange String
import Utils exposing (changePage)

On your questions of ports: Elm's ports are a feature that are on the edge of the architecture. They allow for interop with a different language, so there is, for all intents and purposes, a little magic going on behind the scenes.

Other languages have similar "magical" constructs for interop with other languages. Haskell has Foreign Function Interface (FFI) and C# has the extern keyword to call external libraries.

The definition of Cmd is one of those pieces that doesn't really make sense by looking at the code.

type Cmd msg = Cmd

That doesn't really tell us much, but that's ok. It's more of a placeholder that the compiler fills in on compile time. Other languages do that too. Haskell often uses a bottom call of let x = x in x to signify a function that the compiler will actually implement.

So, unless you're truly interested in the implementation of that crossover between Elm and Javascript, it's ok it leave it to the imagination and accept the magic.

As for being able to specify a concrete type in your port, that's just another choice of the compiler team. Even though a Cmd Event is the only thing that could go through the port, they chose to force a generic type as the Cmd's type parameter. The exact spelling of Cmd msg isn't required. msg could be anything lowercase:

port check : String -> Cmd a
like image 192
Chad Gilbert Avatar answered Dec 06 '22 11:12

Chad Gilbert


Port declaration in Elm by design require a very specific type definition annotation.

Firs of all I would recommend looking into Reading Types and especially in the paragraph mentioning type variables

After that, make sure you are familiar with Generic Data Structures and if the official guide doesn't help, you can look into my answer to the similar question Understanding generic union types in Elm

Ports are slightly confusing so I have opened an issue The guide on JavaScript interop should explain port function type definitions

Outgoing port

port out : String    ->    Cmd msg
              |                 |
              |                 |
          Concrete type    Generic type
          of outgoing      with `msg` type variable
          data             
                           Outgoing port never sends messages,
                           but you need to specify the type so the
                           compiler can infer, that you can use
                           this command to send the outgoing values
                           in any module, that imports "out" function

Incoming port

port in : (List String -> msg)    ->    Sub msg
                     |                     |
                     |                     |
         A function, that accepts       Has to be generic,
         outgoing data and returns      because it is going to be
         a message. This function       a subscription with the
         is called "tagger"             same type as "tagger" returns

         Has to be generic, i.e. use
         `msg` type variable
like image 41
halfzebra Avatar answered Dec 06 '22 12:12

halfzebra