I am learning elm, I've read the documentation and now I'm trying to annotate all the examples trying to explain what happens in each function.
This exercise is taking me quite some time to understand.
What does the next type annotation mean? I get the first parameter is a String and the last Html, but what about the middle one? Is it a Result which is composed by a String field and a List String field?
view : String -> Result String (List String) -> Html
Almost the same as the above, what does those nested types mean?
results : Signal.Mailbox (Result String (List String))
I'll leave the async bit for another question, many thanks in advance!
Result abstracts an operation that could succeed or fail. It is defined as
type Result error value
= Ok value
| Err error
If the operation succeeds the values will be Ok value, otherwise, if it fails, it will be Err error. In your case, the suceed value will be a list of strings, while the error value will be a single message.
For the second point, the thing is similar, results is a mailbox that contains a Result, which will be either Ok (List String) or Err String
Related
Suppose we define a type alias say Message as:
type alias Message a =
{ code : String
, body : a
}
And later define a function readMessage as:
readMessage : Message () -> String
readMessage message =
...
The above example is from Elm tutorial and book says:
This function takes Message with an empty body. This is not the same
as any value, just an empty one.
Can someone please elaborate what exactly happens in above scenario and how compiler handles it.
Unless you really want to see the internal compiler representation of that, I think what's important here is the difference between any value and empty value.
Message a is a parametrized type with 1 parameter. You can read it as a template, e.g. wherever lowercase a appears in the definition of the Message it will be substituted with the concrete type (String, Int, etc).
So this is how function should look like if we want it to take a Message with String body:
readMessage : Message String -> String
readMessage message =
What happens here is that the type of body field is no longer an a but a String (a is substituted with String):
{ code : String
, body : String
}
The value of nothing (aka void or unit) in Elm is encoded as (). That's why a Message with empty body value looks like this:
{ code : String
, body : ()
}
But when we simply don't care about the body value we can just take a Message with any value:
readMessage : Message a -> String
readMessage message =
The lowercase a can be any lowercase string, we can make it more readable like this:
readMessage : Message any -> String
readMessage message =
But then we cannot really read message body, because we don't know the type of it (so we don't know how to read it).
Hope that helps.
The type Message () is an alias for the following record:
{ code : String
, body : ()
}
where the () type denotes a tuple without any items (also known as null tuple). There is only one value of such type and it is also written ().
Now, when we want to omit some field in a record, we cannot just not specify it – that would make the compiler rightly mad, see also The Billion Dollar Mistake. We need to tell the compiler that the value can be omitted.
One way we could do it is to use the Maybe type but if we made a list of messages that would allow us to include the body in some messages and omit it in others. This might not be what we want.
The alternative is to parametrize the Message type as you are doing in the question. This will allow us to have a messages with String bodies when reading the message, and with a different body type when we are not interested in the body.
In this case, we need to consider what the body type should be. While we could use an empty Strings for messages with omitted bodies, they would be easily confused with messages with empty bodies. We could also use Bool but then we would need to decide if we want to use True or False for the omitted value. Finally, we can use the null tuple; since it only has one possible value it is ideal for us.
There is actually one more possibility: we could create a type alias MessageWithoutBody = { code: String }. This is cleaner in some cases (especially when you need to omit more fields) but can be more verbose as you need to duplicate all the fields you want to keep.
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.
My knowledge about list operations is from scripting languages. So in Java I stopped on something strange in case of finding cookie with particular name.
List<Cookie> cookies = Arrays.asList(request.getCookies());
String auth = cookies.stream()
.filter(c -> c.getName().equals("auth"))
.map(Cookie::getValue);
On the map method IntelliJ is showing me "Cyclic inference".
Java compiler Error:(52, 25) java: incompatible types: no instance(s) of type variable(s) R exist so that java.util.stream.Stream conforms to java.lang.String
Your current code returns a Stream<String>, so you need an extra step to return a string:
Optional<String> auth = cookies.stream()
.filter(c -> c.getName().equals("auth"))
.map(Cookie::getValue)
.findAny();
Note that it returns an Optional<String> because there may be no Cookie that matches "auth". If you want to use a default if "auth" is not found you can use:
String auth = cookies.stream()
.filter(c -> c.getName().equals("auth"))
.map(Cookie::getValue)
.findAny().orElse("");
In essence, what this rather cryptic error message is saying is "the output of the stream sequence doesn't match what you are assigning it to in the end", ex:
String s = list.stream().map(s -> s); // this doesn't result in a String...
.findFirst().get()
So to debug compilation, remove the assignment (temporarily), or, as the other answer says, add something that makes it return a String by collecting (ex: .collect(Collectors.joining(","))) or (getting like .findFirst().get()), or change the assignment, like Stream<String> stream = list.stream().map(...)
I am fairly new to VB net and have been playing around with dictionaries for the past week. I have a problem however when trying to do something rather complex with my dictionary look-up.
First, I should point out that I am filling my dictionary with a class object in order to store multiple values:
Class NodeLoad
Public Property NodeName As String
Public Property NodeCase As String
Public Property NodeAxis As String
Public Property NodeDir As String
Public Property NodeValue As Double
End Class
And my problem lies in doing a dictionary look-up where my only option is to do a try catch for when the value I am looking for doesn't exist:
Try
tempnodeitem = (From load In load_dict.Values Where load.NodeName = nodenum And load.NodeCase = pattern And load.NodeDir = dirarray(d)).First
loadforce(d) = tempnodeitem.NodeValue
Catch ex As Exception
loadforce(d) = "0"
End Try
The above code runs, but it takes much longer than I would expect, and after a little research found that try/catch takes much longer than TryGetValue. The thing I would like to do (since it is a much for efficient function) is to use TryGetValue. However, as far as I know, it only works for one key and one value (TKey, TValue).
Can anyone give me an example of how to use TryGetValue with multiple conditions?
Or perhaps how to catch false dict look-ups without being resource intensive?
I am thinking a good way to approach this problem is using nested TryGetValue statements... or possibly multiple dicts or lists which can handle this problem differently.
I appreciate any input!
Thanks!
As you're using a function anyway, I would tend to use function syntax in this case rather than query syntax. Is it possible that there could be more than one match to your conditions? There are four similar methods, i.e. First, Single, FirstOrDefault and SingleOrDefault, and there is never a case where more than one is appropriate. The choice of which to use comes down to two simple questions:
Will there always be at least one match? If not then use one that ends with "OrDefault".
Will there ever be more than one match? If not then use one that starts with "Single".
The answers to those two questions will always tell you which of the four methods to call.
Now, you're using a Dictionary in this case, right? What are the keys? I would have thought NodeName would be but I guess not. Anyway, assuming that there will be zero or one matches to your conditions, you would use SingleOrDefault. The code for FirstOrDefault would look exactly the same anyway:
Dim item = myDictionary.Values.SingleOrDefault(Function(nl) nl.NodeName = nodenum AndAlso
nl.NodeCase = pattern AndAlso
nl.NodeDir = dirarray(d))
loadforce(d) = If(item Is Nothing, 0.0, item.NodeValue)
Notice two other corrections to your code: the proper use of AndAlso instead of And as well as the assignment of a Double value to loadforce(d) rather than a String if there is no match. The NodeValue property is type Double so how can you want a Double if there is a match and a String if there isn't?
I'm calling a function that returns a string, but it's only actually returning the first character of the string it's supposed to be returning.
Here's a sample piece of code to recreate the issue I'm experiencing:
Public Function GetSomeStringValue(Value as Integer) As String
... Code Goes here
Return Some_Multicharacter_string
End Function
The function call looks like:
SomeStringValue = GetSomeStringValue(Value)
Why is this not returning the entire string?
Note: this answer was originally written by the OP, Kibbee, as a self-answer. However, it was written in the body of the question, not as an actual separate answer. Since the OP has refused repeated requests by other users, including a moderator, to repost in accordance with site rules, I'm reposting it myself.
After trying a hundred different things, refactoring my code, stepping through the code in the debugger many times, and even having a co-worker look into the problem, I finally, in a flash of genius, discovered the answer.
At some point when I was refactoring the code, I changed the function to get rid of the Value parameter, leaving it as follows:
Public Function GetSomeStringValue() As String
... Code Goes here
Return Some_Multicharacter_String
End Function
However, I neglected to remove the parameter that I was passing in when calling the function:
SomeStringValue = GetSomeStringValue(Value)
The compiler didn't complain because it interpreted what I was doing as calling the function without brackets, which is a legacy feature from the VB6 days. Then, the Value parameter transformed into the array index of the string (aka character array) that was returned from the function.
So I removed the parameter, and everything worked fine:
SomeStringValue = GetSomeStringValue()
I'm posting this so that other people will recognize the problem when/if they ever encounter it, and are able to solve it much more quickly than I did. It took quite a while for me to solve, and I hope I can save others some time.