update function union type model elm - elm

I have a model:
type Model
= InitialScreen
| ErrorScreen Http.Error
| List NormalRegion
and update function:
update : Msg -> a -> ( Model, Cmd msg )
update msg model =
case msg of
FetchFail e ->
( ErrorScreen e, Cmd.none )
ShowRegions dto ->
( GeographiesDecoder.toNormalRegions dto.regions dto.countries, Cmd.none )
HoverRegion r ->
( model, Cmd.none )
where toNormalRegions is
toNormalRegions : List Region -> List Country -> List NormalRegion
Compiler throws error on update fn:
The 1st and 2nd branches of this `case` produce different types of values. - The 1st branch has this type:
( Model, Cmd msg )
But the 2nd is:
( List NormalRegion, Cmd msg )
Is there a way to cast List into Model?

You have a Model type constructor named List which is conflicting with the built-in List type. I suspect you are actually trying to use an actual list of regions, but that is not represented by what you have coded.
I think you would be better served by defining a non-overlapping constructor:
type Model
= InitialScreen
| ErrorScreen Http.Error
| Regions (List NormalRegion)

Related

Count the number of times a string appeared in a delimited field In BIGQUERY

I have a dataset with a delimiter "->" like:
ROW 1- "Q -> Res -> tes -> Res -> twet"
ROW 2- "rw -> gewg -> tes -> Res -> twet"
ROW 3- "Y -> Res -> Res -> Res -> twet"
I just want to count the number of "Res" in every row
Output would be:
ROW 1- 2
ROW 2- 1
ROW 3- 3
Ive tried writing the following queries but they arnt counting correctly or only counting once:
countif(distinct(lower(FIELD_NAME) like '%Res%'))
count(split(regexp_extract(FIELD_NAME, '(.*?)Res'), '->'))
(trim(Array_reverse(split(regexp_extract(FIELD_NAME, '(.*?)Res'), '->')))
count(regexp_extract(trim(FIELD_NAME), 'Res'))
count(regexp_contains(trim(FIELD_NAME), 'Res'))
Consider below
select id,
( select count(*)
from unnest(split(text, ' -> ')) word
where word = 'Res'
) cnt
from your_table
if applied to sample data as in your question
output is
You may try and consider the below approach using REGEXP_EXTRACT_ALL():
select str,
array_length(REGEXP_EXTRACT_ALL(str, r'\sRes\s')) as Res_count
from your_table
Output:
You may refer to this documentation for more information in using this BigQuery string function.

how to query for values in a deep nested json array in Postresql?

I have a column of json objects (jsonb type) in Posgresql in this format:
[ {"qos1": [ {
"country_id" : [{"id":"IT",...}, {"id":"FR",...},...]
},...],...}
...]
So I am dealing with deep nested arrays of jsons.
I need to retrieve the row containing qos1 -> country_id -> id:"FR"
How to do this?
I tried different combinations such as:
SELECT *
FROM mytable
WHERE datacolumn -> 'qos1' -> 'country_id' -> 'id' = '"FR"'
with no luck.
You can use a JSON path expression:
select *
from the_table
where datacolumn ## '$.qos1[*].country_id[*].id == "FR"'

Is there a way to pass the name of a field to a setter function?

Here I have several functions that all just set a single field on a model record.
In a more dynamic language, I'd just have a single setter function and pass it the name of the field (as a string) and the value that I want to set on the model object.
Is there a way to pass the name of the field in Elm?
What's the Elm way of doing something like this?
type alias Patient =
{ id : String
, name : String
, dateOfBirth : String
, sex : String
... other fields
}
setPatientName : Patient -> String -> Patient
setPatientName patient value =
{ patient | name = value }
setPatientDateOfBirth : Patient -> String -> Patient
setPatientDateOfBirth patient value =
{ patient | dateOfBirth = value }
setPatientSex : Patient -> String -> Patient
setPatientSex patient value =
{ patient | sex = value }
... many others
-- idx is the index of the patient in the model (which is an array of patients)
-- UpdateCell is a variant of my Msg type, like this: UpdateCell Int (Patient -> String -> Patient) String
onInputHandler : Int -> (Patient -> String -> Patient) -> String -> Msg
onInputHandler idx setter inputText =
UpdateCell idx setter inputText
-- idx is the index of the patient in the model (which is an array of patients)
createTableRow : Int -> Patient -> Html Msg
createTableRow idx patient =
...
, input [ type_ "text", onInput (onInputHandler idx setPatientName), value patient.name ] []
, input [ type_ "text", onInput (onInputHandler idx setPatientDateOfBirth), value patient.dateOfBirth ] []
...
I'm currently using each of these functions as an event handler for input elements. So I need a function that I can use for handling the input event. Ideally, I'd define just a single function and use that single one for all the input elements and pass it the field I want to update on the patient record.
The short answer is "no". But this seems a bit like an XY problem. It's not clear what benefit you are trying to achieve since the full application of such a function would be longer than the equivalent record update expression:
setField "name" patient value
-- vs
{ patient | name = value }
and as a partially applied function is only slightly shorter than the equivalent anonymous function with shortened argument names:
setField "name"
-- vs
\r x -> { r | name = x }
Although the latter is significantly noisier with all the symbols.
There is also a short-hand function for getting a record field:
.name
-- vs
\r -> r.name
So there is some precedent for having a dedicated syntax for setter functions too, but unfortunately there is not. Likely because it would complicate the language, and the syntax in particular, for relatively little benefit. I'm therefore curious about what you're actually trying to accomplish.
Edit after question update:
Putting functions in the Msg is a very bad idea because it goes against the Elm Architecture. It makes the state transition opaque and won't work very well with the debugger. When something goes wrong you can still see the state before and after, but you'll have trouble understanding what happened, and why it happened, because that information is encoded in an opaque function which probably isn't the one it should be.
You'll also have trouble factoring your logic. If you need something to happen only when a certain field updates, you might have to put the logic in the view, or special-case that field by putting the logic for that in update while the rest is in view, for example. Either way, you're on the path to a messy code base.
You should generally use names for messages that describe what happened, not what to do, because that tends to lead to an imperative mindset. Instead of UpdateCell you could call it InputChanged, for example. Then instead of the function you should have an identifier for the field. Ideally a custom type, like InputChanged Name, but even a string will work, though it will be much easier to miss a typo.
So instead of setter functions for each field you'll just case match the message and set the field in the update function:
InputChanged Name value ->
{ patient | name = value }
-- vs
setPatientName : Patient -> String -> Patient
setPatientName patient value =
{ patient | name = value }
Then if you need to clear the sex when the name changes, for example (because reasons...), you can simply do:
InputChanged Name value ->
{ patient | name = value, sex = "" }
The Elm Architecture is good because it makes changes easy and safe, not because it's concise and free of boiler-plate. Good Elm code often has a lot of copy-and-paste, but that's not always bad.

Postgres: Loop through json array equivalent in SQL?

I am using postgres 9.6.3 and need to convert the following python code to a sql query:
data = response.json()
activities = data['Response']['data']['activities']
for activity in activities:
activityHash = int(activity['activityHash'])
if activityHash == 2659248071:
clears = int(activity['values']['activityCompletions']['basic']['value'])
The table has two columns: (membershipid integer primary key, data jsonb). I am not sure how to handle an array like this in sql. The array is variable length and might or might not include an entry where activityHash == the desired value.
The desired result from the query would be something like SELECT membershipid, clears FROM table.
I was looking for jsonb_array_elements(activities)
I recommend you check out this link that walks you through how to traverse JSONB in Postgres.
Try the following query and see if that works for you:
SELECT
membershipid,
'data' -> 'activity' -> 'response' -> 'data' -> 'activities' ->> 'activityHash' AS activityHash,
'data' -> 'activity' -> 'response' -> 'data' -> 'activities' -> 'activityHash' -> 'values' -> 'activityCompletions' -> 'basic' ->> 'value' AS clears
FROM yourtablename
WHERE
('data' -> 'activity' -> 'response' -> 'data' -> 'activities' ->> 'activityHash')::int = 2659248071;

Pattern match a polymorphic type in a concrete type in Elm

I'm using elm-form: https://github.com/etaque/elm-form/, and I need to pattern match a polymorphic type into a concrete type, however I got the next error:
The pattern matches things of type:
TranslationId
But the values it will actually be trying to match are:
e
Hint: Your type annotation uses type variable `e` which means any type of value
can flow through. Your code is saying it CANNOT be anything though! Maybe change
your type annotation to be more specific? Maybe the code has a problem? More at:
<https://github.com/elm-lang/elm-compiler/blob/0.18.0/hints/type-annotations.md>
The code in question is this:
translateError : ErrorValue e -> String
translateError error =
case error of
InvalidEmail ->
translate English ErrInvalidEmail
Empty ->
translate English ErrEmpty
CustomError PasswordNotMatch ->
translate English PasswordNotMatch
x ->
toString x
ErrorValue type https://github.com/etaque/elm-form/blob/f9480cb8646ebc9f78f13d3a7482c463c5275776/src/Form/Error.elm#L19:
type ErrorValue e
= Empty
| InvalidString
| InvalidEmail
| InvalidUrl
| InvalidFormat
| InvalidInt
| InvalidFloat
| InvalidBool
| InvalidDate
| SmallerIntThan Int
| GreaterIntThan Int
| SmallerFloatThan Float
| GreaterFloatThan Float
| ShorterStringThan Int
| LongerStringThan Int
| NotIncludedIn
| CustomError e
TranslationId type https://github.com/werner/madison-elm/blob/master/src/elm/Translations/Utils.elm#L9:
type TranslationId
= ErrInvalidEmail
| PasswordNotMatch
| ErrEmpty
I came up with a solution, but it looks weird and I'm not sure if it's the right one https://github.com/werner/madison-elm/blob/master/src/elm/Translations/FormErrors.elm#L7:
translateError : ErrorValue e -> String
translateError error =
case error of
InvalidEmail ->
translate English ErrInvalidEmail
Empty ->
translate English ErrEmpty
CustomError e ->
case (toString e) of
"PasswordNotMatch" ->
translate English PasswordNotMatch
x ->
toString x
x ->
toString x
As #reactormonk says, you are not addressing the type variable in your type definition. elm-form provides flexibility in the custom error through this type variable, which you have to supply yourself if you want to use custom errors (if you do not then you can use the variable throughout your code with no problem).
In particular ErrorValue has a type variable e that you need to specify: it does not matter in the code that does not use the CustomError constructor, but does matter in translateError because you are trying to pattern match on CustomError. It looks as though the type you want is TranslationId so you want
translateError : ErrorValue TranslationId -> String
translateError error =
case error of
InvalidEmail ->
translate English ErrInvalidEmail
Empty ->
translate English ErrEmpty
CustomError PasswordNotMatch ->
translate English PasswordNotMatch
x ->
toString x