ELM QueryString parser dont compile - functional-programming

I am really trying to learn a bit of ELM, but my mind collapse at the query parse, my idea was to create a function to get a query string value by name something like: given an query string ?name=Neuber a function like this getParam "name" that would return Neuber
But its failing at most basic example, it doesn't even compile
page comes from here
routeParser comes from here
module Main exposing (..)
-- import Url.Parser exposing (Parser, (</>), (<?>), oneOf, s)
import Url.Parser.Query exposing (int, map, map2, string)
type alias QueryParams =
{ search : Maybe String
, page : Maybe Int
}
routeParser : Url.Parser.Query.Parser QueryParams
routeParser = map2 QueryParams (string "search") (int "page")
page : Url.Parser.Query.Parser Int
page = map (Result.withDefault 1) (int "page")
The error i got
-- TYPE MISMATCH ---------------- /a/long/way/to/project/src/Main.elm
The 2nd argument to `map` is not what I expect:
15| page = map (Result.withDefault 1) (int "page")
^^^^^^^^^^
This `int` call produces:
Url.Parser.Query.Parser (Maybe Int)
But `map` needs the 2nd argument to be:
Url.Parser.Query.Parser (Result x number)
Hint: I always figure out the argument types from left to right. If an argument
is acceptable, I assume it is “correct” and move on. So the problem may actually
be in one of the previous arguments!

The immediate problem is that int "page" will return a Maybe Int, but you're trying to use it with Result.withDefault, which, as the error message says, expects a Result. The fix for this is just to use Maybe.withDefault instead.

Related

TryGetInt32 throws System.InvalidOperationException

Call me crazy, but I was under the impression that there was a convention of try which meant give it a go, but if you can't then get back to me and let me know that it was a "no-go".
I have recently started a new project and I have decided to use System.Text.Json instead of Newtonsoft since it has been out for a while now and I like to play with new things.
I have the following bit of code in a JsonConverter:
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
if (jsonDoc.RootElement.TryGetInt32(out int number))
{
}
}
When it is a number, it works awesomely, but when it is anything but a number, it throws as if I was calling GetInt32().
In the custom converter, I sometimes get a number back, but I also can get an object back which contains the number that I am expecting as well as a string. I thought that I would be able to test for this using the TryGetInt32 method.
I have two questions:
How could I test if I am getting the number back, or getting the number AND the string?, and
What is the difference between TryGetInt32(out int number) and GetInt32()?
TryGetInt32 throws exception if the value is not a number type.
It does not throw and returns false if the value is a number type but not a number kind convertible to int32.
I hope the following additional check helps:
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
if(jsonDoc.RootElement.ValueKind == JsonValueKind.Number &&
jsonDoc.RootElement.TryGetInt32(out int number))
{
}
}
first question :
using int.TryParse(variable,result) : this return bool and store variable if integer in result
example:
string json = "5";
int result;
if (int.TryParse(json, out result))
{
Console.WriteLine(result);
}
second question:
TryGetInt32(Int32) :Attempts to represent the current JSON number as an Int32 and return bool .
Getint32(): get specific value as int32 in this case you must be sure that the value is integer

What's a good pattern to manage impossible states in Elm?

Maybe you can help. I'm an Elm beginner and I'm struggling with a rather mundane problem. I'm quite excited with Elm and I've been rather successful with smaller things, so now I tried something more complex but I just can't seem to get my head around it.
I'm trying to build something in Elm that uses a graph-like underlying data structure. I create the graph with a fluent/factory pattern like this:
sample : Result String MyThing
sample =
MyThing.empty
|> addNode 1 "bobble"
|> addNode 2 "why not"
|> addEdge 1 2 "some data here too"
When this code returns Ok MyThing, then the whole graph has been set up in a consistent manner, guaranteed, i.e. all nodes and edges have the required data and the edges for all nodes actually exist.
The actual code has more complex data associated with the nodes and edges but that doesn't matter for the question. Internally, the nodes and edges are stored in the Dict Int element.
type alias MyThing =
{ nodes : Dict Int String
, edges : Dict Int { from : Int, to : Int, label : String }
}
Now, in the users of the module, I want to access the various elements of the graph. But whenever I access one of the nodes or edges with Dict.get, I get a Maybe. That's rather inconvenient because by the virtue of my constructor code I know the indexes exist etc. I don't want to clutter upstream code with Maybe and Result when I know the indexes in an edge exist. To give an example:
getNodeTexts : Edge -> MyThing -> Maybe (String, String)
getNodeTexts edge thing =
case Dict.get edge.from thing.nodes of
Nothing ->
--Yeah, actually this can never happen...
Nothing
Just fromNode -> case Dict.get edge.to thing.nodes of
Nothing ->
--Again, this can never actually happen because the builder code prevents it.
Nothing
Just toNode ->
Just ( fromNode.label, toNode.label )
That's just a lot of boilerplate code to handle something I specifically prevented in the factory code. But what's even worse: Now the consumer needs extra boilerplate code to handle the Maybe--potentially not knowing that the Maybe will actually never be Nothing. The API is sort of lying to the consumer. Isn't that something Elm tries to avoid? Compare to the hypothetical but incorrect:
getNodeTexts : Edge -> MyThing -> (String, String)
getNodeTexts edge thing =
( Dict.get edge.from thing.nodes |> .label
, Dict.get edge.to thing.nodes |> .label
)
An alternative would be not to use Int IDs but use the actual data instead--but then updating things gets very tedious as connectors can have many edges. Managing state without the decoupling through Ints just doesn't seem like a good idea.
I feel there must be a solution to this dilemma using opaque ID types but I just don't see it. I would be very grateful for any pointers.
Note: I've also tried to use both drathier and elm-community elm-graph libraries but they don't address the specific question. They rely on Dict underneath as well, so I end up with the same Maybes.
There is no easy answer to your question. I can offer one comment and a coding suggestion.
You use the magic words "impossible state" but as OOBalance has pointed out, you can create an impossible state in your modelling. The normal meaning of "impossible state" in Elm is precisely in relation to modelling e.g. when you use two Bools to represent 3 possible states. In Elm you can use a custom type for this and not leave one combination of bools in your code.
As for your code, you can reduce its length (and perhaps complexity) with
getNodeTexts : Edge -> MyThing -> Maybe ( String, String )
getNodeTexts edge thing =
Maybe.map2 (\ n1 n2 -> ( n1.label, n2.label ))
(Dict.get edge.from thing.nodes)
(Dict.get edge.to thing.nodes)
From your description, it looks to me like those states actually aren't impossible.
Let's start with your definition of MyThing:
type alias MyThing =
{ nodes : Dict Int String
, edges : Dict Int { from : Int, to : Int, label : String }
}
This is a type alias, not a type – meaning the compiler will accept MyThing in place of {nodes : Dict Int String, edges : Dict Int {from : Int, to : Int, label : String}} and vice-versa.
So rather than construct a MyThing value safely using your factory functions, I can write:
import Dict
myThing = { nodes = Dict.empty, edges = Dict.fromList [(0, {from = 0, to = 1, label = "Edge 0"})] }
… and then pass myThing to any of your functions expecting MyThing, even though the nodes connected by Edge 0 aren't contained in myThing.nodes.
You can fix this by changing MyThing to be a custom type:
type MyThing
= MyThing { nodes : Dict Int String
, edges : Dict Int { from : Int, to : Int, label : String }
}
… and exposing it using exposing (MyThing) rather than exposing (MyThing(..)). That way, no constructor for MyThing is exposed, and code outside of your module must use the factory functions to obtain a value.
The same applies to Edge, wich I'm assuming is defined as:
type alias Edge =
{ from : Int, to : Int, label : String }
Unless it is changed to a custom type, it is trivial to construct arbitrary Edge values:
type Edge
= Edge { from : Int, to : Int, label : String }
Then however, you will need to expose some functions to obtain Edge values to pass to functions like getNodeTexts. Let's assume I have obtained a MyThing and one of its edges:
myThing : MyThing
-- created using factory functions
edge : Edge
-- an edge of myThing
Now I create another MyThing value, and pass it to getNodeTexts along with edge:
myOtherThing : MyThing
-- a different value of type MyThing
nodeTexts = getNodeTexts edge myOtherThing
This should return Maybe.Nothing or Result.Err String, but certainly not (String, String) – the edge does not belong to myOtherThing, so there is no guarantee its nodes are contained in it.

How to communicate with a polymorphic child component in Elm?

My main program has an update function of
update : Msg -> Model -> ( Model, Cmd Msg )
To communicate with sub-components we can add another variant and wrap our messages in a new message
type alias Model =
{ ...
, child : Child.Model
}
type Msg
= ...
| ChildMsg Child.Msg
update msg model =
case msg of
...
ChildMsg childMsg ->
let
( childModel, cmd ) =
Child.update childMsg model.child
updatedModel =
{ model | child = childModel }
childCmd =
Cmd.map ChildMsg cmd
in
( updatedModel, childCmd )
However this seem challenging if the type of my sub-component's update function does not match the parent. Consider a child with a polymorphic update function:
-- PolymorphicChild.elm
update : Msg a -> Model -> ( Model, Cmd (Msg a) )
When running a command from this module, I must wrap it
PolymorphicChild.someCommand : Cmd (Msg Foo)
PolymorphicChild.someCommand
|> Cmd.map PolymorphicChild
However, this produces a Msg (PolymorphicChild.Msg Foo), not the Msg PolymorphicChild.Msg my App is expecting.
The right side of (|>) is causing a type mismatch.
(|>) is expecting the right side to be a:
Cmd (PolyMorphicChild.Msg Foo) -> a
But the right side is:
Cmd Polymorphic.Msg -> Cmd Msg
I tried adding a polymorphic parameter to App.Msg
-- App.elm
type Msg a =
= ..
| PolymorphicChildMsg (PolymorphicChild.Msg a)
But it basically blows up my entire program. Every function involving App.Msg needs to somehow be changed to work with the new child component.
How can I unify the two types and get the two components working together?
I think the problem is that you're leaking too much information in your publicly exposed Msg type. Your use of the type parameter of Msg a seems limited to a known set of types, either an Author, Category, Post, or Tag. From skimming your code, it looks like it will never be anything but one of those four, so the fact that you are abstracting things in this manner should be kept inside of this module rather than exposing it and burdening any other code that may be pulling this in.
I think you need to move the abstraction down a level to avoid parameterizing your public Msg type. I would suggest having four concrete constructors for Msg instead of parameterizing it, and shift the abstraction down to a helper LoadInfo a type:
type alias LoadInfo a =
{ worker : Worker a
, url : Url
, result : Result Http.Error ( Int, List a )
}
type Msg
= LoadPost (LoadInfo Post)
| LoadCategory (LoadInfo Category)
| LoadTag (LoadInfo Tag)
| LoadAuthor (LoadInfo Author)

Understanding Elm's Type Signature return types

I am trying to understand elm's type signatures. What does this function return exactly? It appears to be a function that accepts no arguments and returns ...
route : Parser (Page -> a) a
As a learning exercise for myself I'm going to try to answer this. Others will chip in if I get something wrong.
I'm sure you are used to something like
type Person = Adult String | Child String Age
Child is a type that takes two parameters. Parser is the same. But it's definition is pretty formidable
type Parser a b =
Parser (State a -> List (State b))
type alias State value =
{ visited : List String
, unvisited : List String
, params : Dict String String
, value : value
}
That said, you see how Parser is ultimately a wrapper around a function from a State to a list of States. Ultimately it is going to be passed a List of 'unvisited' strings or params; it will progressively 'visit' each one and the result will be combined into the final 'value'.
Next, note that while Parser takes two type parameters - a, b - parseHash is defined
parseHash : Parser (a -> a) a -> Location -> Maybe a
So, your original
route : Parser (Page -> a) a
is going to have to be
route : Parser (Page -> Page) Page
to type check.
To return to your original question, therefore, route is a Parser (which is a very general object) that encapsulates instructions on how to go from one Page to another, and can be used - via parseHash - to tell you what Page to go to next, and that is of course what you would expect from a router.
Hope this gets you started

Go: reflect : Call with too few input arguments

I've stucked with problems of using reflect library. I descided to use it because of many recomendations, but i'm just learning go and some parts are not really easy..
I've got this part of code :
func countDataByName(sourceName string, statData interface{}, filters Filter, chartName string) []ChartElement {
...
//step 1 - filter
filteredData := reflect.ValueOf(statData).MethodByName("FilterData").Call([]reflect.Value{})
//step 2 - cluster
// clusterData := reflect.ValueOf(filteredData).MethodByName("clusterData").Call([]reflect.Value{})
//step 3 - count
// countedData := reflect.ValueOf(clusterData).MethodByName(chartName).Call([]reflect.Value{})
fmt.Println("Never prints to anywhere", filteredData)
...
return filterData
}
If I execute the method like this, I get error : reflect: Call with too few input arguments. But if I change reflect.ValueOf(statData) on reflect.ValueOf(&statData) than error is reflect: call of reflect.Value.Call on zero Value
statData comes with one of 2 types, and fore this types I have structs and methods, like this :
type NoaggModel struct {
Date string
Hour int
Id_user int
Id_line int
Id_region int
Id_tree_devision int
N_inb int
N_inb_d int
T_ring int
T_inb int
T_inb_d int
T_hold int
T_acw int
T_acw_d int
T_wait int
}
func (ng *NoaggModel) FilterData( data NoaggModel) {
fmt.Println("FilterData")
fmt.Println("data : ", data)
}
this Println also not works. Code panics above , and method was not triggered. Where is my mistake here?
Upd 1:
Found that if I remove param data in functioin that I want to call, than it calls nicely. But!
I have statData as 1 row, of structs, so type is NoaggModel. And in the method FilterData I get this 1 row as ng. But I need to change it to the []NoaggModel. How to call reflect in this case and how to pass parameter to the filter function ?
Upd 2:
I modified few parts :
func (ng *NoaggModel) FilterData(filter interface{}, data NoaggModel) {
fmt.Println("data : ",ng)
}
In here, how to pass correct type to filter, if it is set up in revel controller, and method is in model. Or should I set the type in each model and call it in controller?
And in controller I wrote :
//step 1 - filter
in := make([]reflect.Value, 2)
in[0] = reflect.ValueOf(filters)
in[1] = reflect.ValueOf(statData)
filteredData := reflect.ValueOf(statData).MethodByName("FilterData").Call(in)
StatData is a row of type NoaggModel, but I get the error :
reflect: Call using *models.NoaggModel as type models.NoaggModel
The type was set also by reflect in code above, like this :
...
var sourceTypes = map[string]reflect.Type{
"noagg": reflect.TypeOf(models.NoaggModel{}),
"oracle": reflect.TypeOf(models.OracleModel{}),
}
deserializedData = reflect.New(sourceTypes[sourceName]).Interface()
...
// deserialised becomes statData
Reflection is not easy. And should be avoided if possible.
I admit that I did recommend using reflect to dynamically create instances of types based on a map, which is really useful when you don't know which types you might have to handle. But in your case you should consider using interfaces.
While I don't really know what you want to achieve, I would suggest starting by creating an interface that all your Models need to implement (modify it to fit your needs):
type Model interface {
FilterData(interface{})
}
NoaggModel and OracleModel would then implement the above interface by defining similar methods like this:
func (ng *NoaggModel) FilterData(filter interface{}) {
fmt.Printf("data: %#v, filter: %#v\n", ng, filter)
}
Then, change deserializedData (and statData) to be of the interface type Model instead of interface{}. And since you only have two types, you can avoid using reflect by having a switch instead:
...
var deserializedData Model
switch sourceName {
case "noagg":
deserializedData = new(models.NoaggModel)
case "oracle":
deserializedData = new(models.OracleModel)
}
...
// Marshal the values into deserializedData which now holds an instance of the desired type
...
deserializedData.FilterData("Replace this string with your filter")
And it is done without having to import reflect!

Resources