I'm just starting on elm and without understanding Haskell and its compiler
I'm trying to grasp what the signature mean in Html.program
func: (a -> String) -> String -- this means expects a function and return a string
main: Program Never Model Msg -- What does this mean?
Program is a type parameterized by three type variables: flags, model, and msg. Never is a type that cannot have any value (see the link for a good explanation of what this means and how it differs from the unit type ()).
Program Never Model Msg therefore is the type of a program that doesn't have any flags (Never), has a model of type Model, and passes messages of type Msg.
Related
So I'm trying to define a method like this
fun <R,F> myFunction(prop: KProperty1<R, F>, value:F) {}
// so that the compiler only allows me to invoke it like
myFunction(User::name, "Alejandro")
// and stops developers from doing illegal things like
myFunction(User::name, 123)
//However, compiler doesn't complain if I do that... it widens the type to Any
How can I achieve that?
Kotlin is "widening" the type here because the value type parameter (i.e. the second type parameter) of KProperty1 is defined with keyword out which makes that parameter covariant.
This means that for instance KProperty1<User, String> is a subtype of KProperty1<User, Any>, and hence User::name which is presumably a KProperty1<User, String>, can also be seen as a special case of KProperty<User, Any>. Therefore, it is totally legal to call myFunction<User,Any>(User::name, 123).
The logic behind this can be derived from the name of the out keyword: It is expected that the typed parameter is only used in "out position" of any function call. In the case of KProperty1 this makes sense, because it is the type of the return value of the property. When you get a value from a KProperty1<K, V>, that value is of type V and thus it can be used anywhere where it is okay to have some supertype of V.
This should only be a problem, if you want to use the value in the "in position" of some function, for instance, if you want to write a function that takes a value of type V and store it in a KProperty1<K, V>.
If this is what you want, you are lucky, because you can and should just use KMutableProperty1<K,V> where the value parameter does not have an out keyword which means that it is invariant. Also, that interface allows you to put the value into the property.
Changing your function definition to
fun <R,F> myFunction(prop: KMutableProperty1<R, F>, value:F) {}
makes that the compiler allows myFunction(User::name, "Alejandro"), but it complains on myFunction(User::name, 123).
See also: Kotlin documentation on Variance
I have a following piece of Elm code (getProjectView function is omitted for brievity):
type Model = Maybe List Project
model : Model
model = Nothing
getView : Model -> Html any
getView model =
case model of
Just projects ->
ul [] (List.map getProjectView projects)
Nothing -> p [] [ text "Still loading..." ]
When I try to compile the following snippet, the compiler fails with the following error:
-- TYPE MISMATCH --------- E:\dev\irrelephant-code\client\elm\Views\Projects.elm
Tag `Maybe.Just` is causing problems in this pattern match.
32| Just projects ->
^^^^^^^^^^^^^
The pattern matches things of type:
Maybe a
But the values it will actually be trying to match are:
Model
Indicating that compiler can't deduce that this Nothing is a value of type Model (which in turn is an alias of type Maybe List Project).
What am I doing wrong here? Is there a way to explicitly mark this Nothing as a value of the Model type?
I am using elm v0.18.0
You want to define model as a type alias of Maybe (List Product). Right now, with the type keyword, you are defining a new union/tag type with one value, Maybe, which expects to arguments, of type List and Product.
A working example is https://ellie-app.com/3MhPcgGzXqRa1/0
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.
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
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
Your first compiler error is because your import succeeds a definition, but the required format is to have all imports preceding all definitions.
As for what msg in String -> Cmd msg means, it is simply a type variable - all lowercase type names in type annotations in Elm are type variables, while those beginning with an uppercase letter are concrete types. So it's the same as String -> Cmd a or String -> Cmd foo.
In Elm, like in Haskell and some other functional languages, if a type variable is in a type annotation, it is implicitly universally quantified. So we read the above type as
changePage : ∀msg.String → Cmd msg
that is, 'for any type msg, changePage can take a String to a Cmd of msg'.
This means the expression changePage "myPage.html" can be used anywhere in your code where you want a command of some type. This seems to make sense, because it represents the command of 'please send "myPage.html" to anyone subscribed to the changePage port'.
In the Elm language, I'm having a hard time explaining my question...
In these snippets in elm:
I understand the signature in something like
update : Msg -> Model -> Model
where the parameters / output is separated by arrows, but how do I read / grok things like:
Sub Msg
Program Never Model Msg
In:
main : Program Never Model Msg
main =
program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
In a type signature, parameter types are separated by ->, with the last type being the return value.
If there are no -> symbols, then it means it is a value of that type. In your main example, the type of main is Program Never Model Msg. It has no arrows, so it takes no parameters.
Now, each parameter and the return value in the type annotation may have several things separated by spaces, as in your main example. The leftmost is the type, followed by type parameters separated by spaces.
Program Never Model Msg
| | | |
| ------|-----
type type parameters
A type parameter is similar to Generics in a language like C#. The equivalent syntax in C# would be:
void Program<Never, Model, Msg>()
C# doesn't directly correlate because it has a different way of constraining generic type parameters, but the general idea holds.
The Elm guide doesn't currently have a great deal of info, but here is the section talking about types.
Sub Msg, List Int, Program Never Model Msg
Sub, List and Program are type constructors. You can think about them as functions that take a type and return another type.
By themselves, Sub, List and Program are not complete type. They are like a puzzle missing a piece. When one adds the missing piece, the puzzle is complete.
I usually read them in my head using the word of as in a List of Ints, a Program of Never, Model and Msg.
Two questions.
First,
Below is strong type.
String msg = "Hello world.";
msg = "Hello world again.";
And, below dynamic
var msg = "Hello world.";
msg = "Hello world again.";
Is there any difference between the two 'msg's above?
Second, if I use 'new' keyword to initiate a variable as below,
Map myMap = new Map;
Why to indicate the variable 'myMap' is a Map instance(Map myMap) as 'new' keyword already include the same meaning? So, isn't it okay just,
myMap = new Map;
Because the 'new' keyword already implies the newly initiated variable is both variable and Map type, I can't understand why normally 'Map' keyword is with the variable name, even 'var' also.
Does anyone have any idea about this (seems a little bit redundant) Dart grammar?
In regard to the first question, there will be no difference in what each msg variable contains.
For the Map question, the reason for specifying the type of a variable that is constructed at declaration is to allow some flexibility with subclasses. Take for example the following code:
class SubMap extends Map {
SubMap() : super();
}
Map map = new SubMap();
Here we have a variable map which contains a SubMap object as its value, however we are allowing it to contain values of type Map (or other types which subclass Map) at later times.
The main thing to remember with Dart is that it is optionally typed. When running your code, none of your type annotiations make any difference at all (unless you run in checked mode). What the type annotations are for is to help your IDE and other tools provide autocomplete help, possible warnings, etc. which other fully dynamic languages like Javascript cannot.
String msg = "Hello world.";
msg = "Hello world again.";
msg = 1; // exception in checked mode - int can not be assigned to String.
var msg = "Hello world.";
msg = "Hello world again.";
msg = 1; // ok in checked mode
Checked mode is the developer mode where type annotations are checked and create runtime exceptions when code violates them.
In unchecked (production) mode it makes no difference if you add a type annotation and which one. This is for performance reasons because checked mode is slower.
The declaration Map myMap = new Map() does three things:
it declares a variable named myMap with type-annotation Map,
it creates a new object using the Map constructor, and
it assigns the object to the variable.
The type annotation means that myMap has static type Map. The static type can give you some warnings at compile time, but it doesn't change anything at runtime.
The type annotation also adds a type check in checked mode, where any assignment to the variable is checked for being assignable to Map.
The object you create could be any object using any constructor. I regularly use new HashMap() instead of new Map(), and still assign it to a variable typed as Map.
Then the object is assigned to the variable, and the type check succeeds, if in checked mode.
The variable is independent of the value used to initialize it. If you later assign a string to the myMap variable, it will fail in checked mode.
So, the difference between the two msg variables is that one has a static type and a type check in checked mode.
For the code you show, there is no difference in behavior.
If the next line was var y = msg + 42;, then the typed version would give a warning (msg has static type String, and String.operator+ has type String->String, so the 42 has an invalid argument type), where the untyped version wouldn't warn you (msg has type dynamic so you probably know what you are doing).