Type conflict when generating a random list of integers in Elm - elm

This is related to the Elm Tutorials (http://guide.elm-lang.org/architecture/effects/random.html), and am trying to generate a list of random numbers (just 2 items for now) for one of the challenges.
I get a type error when trying to generate the list:
The 2nd argument to function `generate` is causing a mismatch.
39| Random.generate NewFaces intList)
^^^^^^^
Function `generate` is expecting the 2nd argument to be:
Random.Generator List
But it is:
Random.Generator (List Int)
This is the code I am using:
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
Roll ->
let
intList : Random.Generator (List Int)
intList =
Random.list 2 (Random.int 1 6)
in
(model, Random.generate NewFaces intList)
NewFaces newFaces ->
({ model | dieFaces = newFaces}, Cmd.none)
I am still trying to get my head wrapped around types -- particularly with regard to lists. I'm guessing (List Int) means a list of integers, but I am not sure what List by itself means (list of arbitrary type?).
I have played around with the code by pulling out the Generator into a separate variable (intList) and also explicitly typing it. I also tried typing it Random.Generator List, which throws an error also. Basically, I could use help figuring out how to reconcile List vs. (List Int).
Thank you -- super new to Elm, so any guidance is appreciated.

Based on the error message, it looks like you probably have defined NewFaces like this:
type Msg
= Roll
| NewFaces List
List takes a single type parameter, so it should be defined as
type Msg
= Roll
| NewFaces (List Int)

Related

error in elm-lang `(==) is expecting the right side to be a:`

New to elm here, and at first it's driving me absolutely crazy not knowing the ins and outs of this picky language (even after reading a sh**load about it because it's just so different and finicky... I guess that's the nature of a functional lang) so when you try doing a simple thing it's like pulling hair at first.
I am getting the following error:
The right side of (==) is causing a type mismatch.
29| get 0 arrayOfValues == 'X'
^^^
(==) is expecting the right side to be a:
Maybe Char
But the right side is:
Char
Hint: With operators like (==) I always check the left side first. If it seems
fine, I assume it is correct and check the right side. So the problem may be in
how the left and right arguments interact.
Test:
it "blah blah blah" <|
let
someArray =
[ 'P', ' ' ]
in
expect (MyModule.doSomething someArray 'P') to equal 1
MyModule
doSomething : List Char -> Char -> Int
doSomething arrayOfValues symbol =
let
grid =
fromList arrayOfValues
found =
get 0 arrayOfValues == symbol
in
if found then
1
else
0
Now I'm assuming but not sure, that it's getting Nothing or something when trying to pull the first value out of my array but not sure. Maybe Char I assume is returning Nothing? donno, probably have other issues going on with it too.
I'd like to get the code above working, then refactor..I'm sure there's probably a more elegant way to code what I've coded above but first thing's first, fixing this error and understanding it better with the existing code. The error message while nice isn't that obvious to me as to how and what to handle. I have assumptions but not fully sure how to handle the behavior here of whatever is causing the issue.
Unique feature of the elm is certainty. Any variable (which is not of type maybe) will have a value of the defined type for sure.
But when it comes to array or list, it becomes uncertain if the array has an element on index "i". There may be an element and there may not be.
Hence elm has concept of Maybe,
so conceptually
Maybe String = [ Just "string_value" | Nothing ]
the alias for the Array.get is
get : Int -> Array a -> Maybe a
it takes
Int - index and
Array a - array of data type of array element
as parameters and returns
Maybe a - again a is the data type of array element
consider an example
array =
fromList ["one", "two"]
val1 =
get 0 array -- will return 'Just "one"'
val2 =
get 3 array -- will return 'Nothing', since the element does not exists
this way you will always have to handle both the situations, when you have a value and when you don't
case val1 of
Nothing ->
-- Raise some error message
Just val ->
-- `val` is the actual element/value found
and if you always need a default value, you can use
Maybe.withDefault "default_string" val1
this will always return a string value and will return "default_string" when the value is nothing otherwise the actual found value

How to structure message and update functions with a variable number of UI elements in Elm?

Greetings StackOverflow!
Suppose I have an Elm app with a variable number of text input fields. I'd like to reflect the state of these input fields in the model.
Model and view are easy enough: View just has a Array String field in it somewhere.
The view is then computed simply by calling List.map (HTML input ...) on that list of strings.
However, I'm a bit lost how to do the update function and message type.
The message could be somethign like this:
type Msg = InputFieldUpdated Int String
Here, the Int refers to the position in the Array that the string to be updated has. However, if I do it this way, I can create messages that refer to non-existant array positions simply by setting the Int to something that is out of range.
For a fixed number of input elements, one can solve this problem very elegantly by simply using a union type with a different value for each input, but what about my situation? In the domain of "making impossible states impossible", is there some trick for that that I'm missing?
However, if I do it this way, I can create messages that refer to non-existant array positions simply by setting the Int to something that is out of range.
According to the documentation of Array.set, the array stays untouched if the index is out of range.
Please, have a look at this ellie-app example. It mostly models the problem, that you've described. Array of elements is rendered and the elements can be added dynamically:
view : Model -> Html Msg
view model =
div []
[ div [] (toList (Array.indexedMap viewElement model.elements))
, button [ onClick Add ] [ text "Add" ]
]
In order to update a particular element, you need to get it by index. Since the type of the result from Array.get is Maybe a, type system will force you to process all the cases (when the element exists and doesn't):
Increment index ->
case get index model.elements of
Just element ->
{ model | elements = set index (element + 1) model.elements }
Nothing ->
model
The example is just for demonstration purposes, if you don't need the current element, then Array.set function can be safely used.

Expected Int, got IntProgression instead

I am trying to get on Kotlin so I am following this tutorial of their own.
So they're trying to create a sequence given a string, such as this:
"a vect" -> [
a vect :
a vec : t
a ve : ct
...
]
And the way to do it is, according to the video, the following:
val seq = sequenceOf(canonicalisedInput.lastIndex + 1 downTo 0).map {
canonicalisedInput.substring(0, it) to canonicalisedInput.substring(it)
}
And I get what I does (well, the idea of it). The problem is that substring expects two Ints, while it (which I assume is an implicit iterator of some sorts that comes from the downTo progression) is an IntProgression. Same for the second substring call.
What am I missing?
The code you posted contains a mistake: sequenceOf(...) with single argument passed returns a sequence with that one item, that is, Sequence<IntProgression> . To get a sequence of indices (Sequence<Int>), use asSequence() function instead:
(canonicalisedInput.lastIndex + 1 downTo 0).asSequence().map { ... }
The substring(...) function called second is the overload that returns the substring starting from the index passed as the argument.
And it is the implicit name for the innermost lambda single parameter, in your case it is the parameter of map, that is, the sequence item to be mapped by the lambda.
So, the expression inside lambda is a pair (created by to infix function) of two substring, one from the beginning of the original string to the index in the sequence, the other one -- from that index to the end of the string.
So the code should definitely work with indices sequence, that's why the mistake is quite clear.
sequenceOf(canonicalisedInput.lastIndex + 1 downTo 0) —
this expression creates a sequence which consists of a single IntProgression item.
If you want to convert an IntProgression to a Sequence<Int>, use asSequence extension function:
(canonicalisedInput.length downTo 0).asSequence()

Incrementing uniqueID over each List.map iteration

I'm trying to initialise a set of elements with a unique identifier. The elements are part of the initial model.
What I have in mind is a function
initElement: Int -> InputElement -> Output
initElement id element = ...
that adds the given id to the given element. Now I'm iterating over these elements in another function like this:
uid = 0
elementsList = ...
newList = List.map (initElement uid++) elementsList
and I would want this integer uid increased with every iteration over an element by List.map, so that every element gets a unique number assigned. The ++ obviously doesn't work though.
Is this possible, or am I thinking too object-oriented? I'm pretty new to functional programming.
One option is to use List.indexedMap
http://package.elm-lang.org/packages/elm-lang/core/3.0.0/List#indexedMap
It gives you a nice incrementing index as a parameter to your function as first parameter. Which you can then use to modify the incoming uid approriattely

F# Generate SQL from CSV

I have recently been learning F# and functional programming. One application I have found very useful is generating SQL inserts for a data load from a CSV (or excel table) with some associated ID's.
The following code is my result, which I believe I will find very handy in the future. I thought others could also benefit from this and I welcome suggestions and other scripts which people have found invaluable in their collection:
// Returns some dataload SQL for area mapping.
open System
open System.IO
// Read and split CSV into lists
let map_ngo_area = File.ReadAllLines(#"P:\MY_TABLE.csv")
|> Array.to_list
|> List.map(fun x -> (x.Split([|','|])
|> Array.map(fun y -> y.Trim()))
|> Array.to_list)
// Output Formatting function
let format_sql_record = "INSERT INTO MyTable
(ID, REF1_ID, REF2_ID, CreatedUser, CreatedDateTime, LastModifiedUser, LastModifiedDateTime)
VALUES
( {0}, {1}, {2}, 'system', getDate(), 'system', getDate() )"
// Generate the SQL for the given list.
let generate_sql list = list |> List.mapi(fun index row ->
match row with
| [ngo_id; area_id] -> String.Format(format_sql_record, ((int index)+1), ngo_id, area_id) |> printfn "%s"
| _ -> printfn "")
// Main Execution
map_ngo_area |> generate_sql |> ignore
// End of program, pause to view console output.
System.Console.ReadKey() |> ignore
Any suggestions on improving my F# code or process? Comments also welcome, as I am fairly new at this paradigm and shifting thinking is not as forthcoming as I expected.
Thanks :)
Here are a few suggestions:
Don't use List.mapi with functions that return unit, since there's not much you can do with the resulting unit list. You should use List.iteri instead, which will allow you to omit the |> ignore at the end of your main execution section.
Going further, rather than having generate_sql print the generated lines one at a time, it might be better to generate a list of strings instead. Note that in this case, you would go back to using List.mapi since the function that you apply would return a result for each line.
Use F#'s print formatting rather than String.Format. For instance rather than having format_sql_record be a string, have it be a function of type int->string->string->string: let format_sql_record = sprintf "INSERT INTO ... VALUES (%i, %s, %s, ...)"
Depending on the version of F# that you're using, you should probably be using the renamed function Array.toList instead of Array.to_list, since that's the name that will be used in the final release of F#.
You can use pattern matching on arrays too:
let map_ngo_area = File.ReadAllLines(#"P:\MY_TABLE.csv")
|> Array.to_list
|> List.map(fun x -> (x.Split([|','|])
|> Array.map(fun y -> y.Trim()))
let generate_sql list = list |> List.mapi(fun index row ->
match row with
| [| ngo_id; area_id |] -> printfn ...
| _ -> printfn "")