Update Elm record with multiple constructors - elm

Is there a way to modify field for a type with multiple constructors?
type U = S | C { xxx : String }
This is not a record, so it has no fields to update!
5| let c = C { xxx = "DD"} in case c of C {} -> { c | xxx = "ZZ" }
^
This `c` value is a:
U
But I need a record!

In type U = S | C { xxx : String }, xxx is not a field of U. It is a field of the record contained in C. Those are separate types that can be deconstructed into separate values. And the way to do that is to use case to match the C constructor and bind the contained value to a name (or further deconstruct it) so we can refer to it on the right side of the ->.
But then you also need to handle the possibility of c being S. What should be returned then? Maybe a default? Or maybe you actually want to return a U? I've assumed the former here, but the latter would just be construction values of U as you would anywhere else.
let
c =
C { xxx = "DD" }
in
case c of
C record ->
{ record | xxx = "ZZ" }
S ->
-- What to do here?
{ xxx = "default?" }

Related

Sum up the elements of a record

type MyType = {a:int; b:int};;
let test = [{a=5;b=10}; {a=10;b=100}; {a=200; b=500}; {a=100; b=2}];;
I would like to create a function which will sum up a and b in such a way it will display
Sum of a : 315
Sum of b : 612
I think I have to use a recursive function. Here is my attempt :
let my_func record =
let adds = [] in
let rec add_func = match adds with
| [] -> record.a::adds; record.b::adds
| _ -> s + add_func(e::r)
add_func test;;
This function doesn't seem to work at all. Is there a right way to do such function?
OK, you know exactly what you're doing, you just need one suggestion I think.
Assume your function is named sumab and returns a pair of ints. Then the key expression in your recursive function will be something like this:
| { a = ha; b = hb; } :: t ->
let (a, b) = sumab t in (ha + a, hb + b)

difference between two lists that include duplicates

I have a problem with two lists which contain duplicates
a = [1,1,2,3,4,4]
b = [1,2,3,4]
I would like to be able to extract the differences between the two lists ie.
c = [1,4]
but if I do c = a-b I get c =[]
It should be trivial but I can't find out :(
I tried also to parse the biggest list and remove items from it when I find them in the smallest list but I can't update lists on the fly, it does not work either
has anyone got an idea ?
thanks
You see an empty c as a result, because removing e.g. 1 removes all elements that are equal 1.
groovy:000> [1,1,1,1,1,2] - 1
===> [2]
What you need instead is to remove each occurrence of specific value separately. For that, you can use Groovy's Collection.removeElement(n) that removes a single element that matches the value. You can do it in a regular for-loop manner, or you can use another Groovy's collection method, e.g. inject to reduce a copy of a by removing each occurrence separately.
def c = b.inject([*a]) { acc, val -> acc.removeElement(val); acc }
assert c == [1,4]
Keep in mind, that inject method receives a copy of the a list (expression [*a] creates a new list from the a list elements.) Otherwise, acc.removeElement() would modify an existing a list. The inject method is an equivalent of a popular reduce or fold operation. Each iteration from this example could be visualized as:
--inject starts--
acc = [1,1,2,3,4,4]; val = 1; acc.removeElement(1) -> return [1,2,3,4,4]
acc = [1,2,3,4,4]; val = 2; acc.removeElement(2) -> return [1,3,4,4]
acc = [1,3,4,4]; val = 3; acc.removeElement(3) -> return [1,4,4]
acc = [1,4,4]; val = 4; acc.removeElement(4) -> return [1,4]
-- inject ends -->
PS: Kudos to almighty tim_yates who recommended improvements to that answer. Thanks, Tim!
the most readable that comes to my mind is:
a = [1,1,2,3,4,4]
b = [1,2,3,4]
c = a.clone()
b.each {c.removeElement(it)}
if you use this frequently you could add a method to the List metaClass:
List.metaClass.removeElements = { values -> values.each { delegate.removeElement(it) } }
a = [1,1,2,3,4,4]
b = [1,2,3,4]
c = a.clone()
c.removeElements(b)

Get constructor by value option in Elm (0.19.1)

I have some types:
type alias Type1 = { name : String }
type alias Type2 = { name : String, age : Int }
type S
= S1 Type1
| S2 Type2
So, when I want to build my info I can do the following:
a = S1 { name = "Name1" }
b = S2 { name = "Name2", age = 100 }
Now, I would like to get its constructor (S1 or S2) based on the info passed as parameter to the constructorByData function. Examples:
constructorByData a -- It should be returned `S1`
constructorByData b -- It should be returned `S2`
This is my aproach:
constructorByData : S -> (a -> S)
constructorByData s =
case s of
S1 _ -> S1
S2 _ -> S2
Please, note that the above code does not work. I get the following error:
-- TYPE MISMATCH ---------------------------------------------------------- REPL
Something is off with the 2nd branch of this `case` expression:
14| S2 _ -> S2
^^
This `S2` value is a:
Type2 -> S
But the type annotation on `constructorByData` says it should be:
a -> S
-- TYPE MISMATCH ---------------------------------------------------------- REPL
Something is off with the 1st branch of this `case` expression:
13| S1 _ -> S1
^^
This `S1` value is a:
Type1 -> S
But the type annotation on `constructorByData` says it should be:
a -> S
The main reason I want to do this is because I want to do the following by generalizing the message:
type Field
= Name
| Age
type Msg
= UpdateFieldString S Field String
| UpdateFieldInt S Field Int
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UpdateFieldString s field value -> updateFieldString model s field value
UpdateFieldInt s field value -> updateFieldInt model s field value
And is for this I need the constructor in updateField{String, Int} functions

Can't get record property of a record

I have this
{ a |
b = { a.b |
c =
Utils.newC
a.b.c
}
}
But the compiler just says "no" :
-- SYNTAX PROBLEM ----------------------------------------------------- Main.elm
I ran into something unexpected when parsing your code!
43| b = { a.b |
^
I am looking for one of the following things:
"'"
"|"
an equals sign '='
more letters in this name
whitespace
I don't know what to do now. How to get a with c property of b changed to a new value?
Updating nested records is a little more verbose in Elm than in other languages, and the syntax of { a.b | ... } updates is not allowed. Here is an alternative:
let
b = a.b
newB = { b | c = Utils.newC b.c }
in
{ a | b = newB }
See this related question for more information on standard ways of updating nested record values in Elm.

Easiest way of defining and using of Global Variable

"first part" &&&& fun _ ->
let ident
"second part" &&&& fun _ ->
ident ....
I need to use variable "ident".
I just need to pass value of variable from first part of test to second one...
I want to ask you if there is any easy way how to define and use global variable or even if you have better (and easy) idea of doing that
Keep in mind, please, that I am a beginner, so I would prefer easier ones.
Global variables will often make your code difficult to work with - particularly if they are mutable.
Instead, consider returning the values you need to keep track of as composite values. An easy data type to start with would be a tuple:
let ``first part`` id =
let someOtherValue = "Foo"
someOtherValue, id + 1
This function takes an int (the current ID) as input, and returns string * int (a tuple where the first element is a string, and the second element and int) as output.
You can call it like this:
> let other, newId = ``first part`` 42;;
val other : string = "Foo"
val newId : int = 43
Notice that you can use pattern matching to immediately destructure the values into two named symbols: other and newId.
Your second function could also take an ID as input:
let ``second part`` id otherArgument =
// use id here, if you need it
"Bar"
You can call it like this, with the newId value from above:
> let result = ``second part`` newId "Baz";;
val result : string = "Bar"
If you find yourself doing this a lot, you can define a record for the purpose:
type Identifiable<'a> = { Id : int; Value : 'a }
Now you can begin to define higher-order functions to deal with such a type, such as e.g. a map function:
module Identifiable =
let map f x = { Id = x.Id; Value = f x.Value }
// Other functions go here...
This is a function that maps the Value of an Identifiable from one value to another, but preserves the identity.
Here's a simple example of using it:
> let original = { Id = 42; Value = "1337" };;
val original : Identifiable<string> = {Id = 42;
Value = "1337";}
> let result' = original |> Identifiable.map System.Int32.Parse;;
val result' : Identifiable<int> = {Id = 42;
Value = 1337;}
As you can see, it preserves the value 42, but changes the Value from a string to an int.
You can still change the ID explicitly, if you want to do that:
> let result'' = { result' with Id = 7 };;
val result'' : Identifiable<int> = {Id = 7;
Value = 1337;}
Since this was getting out of hand for comments this is how I would do it for an example
let mutable t = 0
let first =
t <- 1 + 1
//other stuff
let second =
//can use t here and it will have a value of 2
In some cases you have to use a ref:
let t = ref 0
let first =
t := 1 + 1
//other stuff
let second =
//can use t here and it will have a value of 2 -
// you use "!t" to get the value
If you define ident at the top of your file like this :
let ident = "foo"
// rest of your code using ident
ident are global and you can use in the next part of your file.
EDIT :
If ident wil change in the next part of your code, use this :
let ident = ref "foo"