It's not clear to me how to retrieve distinct items from a list.
I have the following code:
topicsFromLinks : List Link -> List Topic
topicsFromLinks links =
links
|> List.map (\l -> l.topics)
|> List.concat
|> Set.fromList
|> Set.toList
Error:
The definition of topicsFromLinks does not match its type
annotation. - The type annotation for topicsFromLinks says it always
returns:
List Topic
But the returned value (shown above) is a:
List comparable
I expect the following lines to just work in regards to structural equality:
|> Set.fromList
|> Set.toList
Why am I receiving a List of Comparables?
How do I resolve this compilation error?
Appendix:
type alias Topic =
{ name : String, isFeatured : Bool }
type alias Link =
{
...
, topics : List Topic
...
}
According to the documentation for Set:
The values can be any comparable type. This includes Int, Float, Time, Char, String, and tuples or lists of comparable types.
You are attempting to put a Topic value in where only a comparable type will work.
Thankfully there is the elm-community/list-extra package which exposes a uniqueBy function that lets you specify your own function to turn something into a comparable.
If you want to get the distinct list of topics, matching both on the name and isFeatured fields, then you can use toString to serialize the value into something comparable:
import List.Extra exposing (uniqueBy)
topicsFromLinks : List Link -> List Topic
topicsFromLinks links =
links
|> List.map .topics
|> List.concat
|> uniqueBy toString
In 2021, rather than using an external library and writing a clumsy toString method (since Debug.toString isn't available for production use anymore), consider using a fold:
unique : List a -> List a
unique list =
List.foldl
(\a uniques ->
if List.member a uniques then
uniques
else
uniques ++ [ a ]
)
[]
list
Related
I'm trying to figure out the best way to push data from a dataframe (DF) into a SQL Server table. I did some research on this yesterday and came up with this.
import com.microsoft.azure.sqldb.spark.config.Config
import com.microsoft.azure.sqldb.spark.connect._
// Aquire a DataFrame collection (val collection)
val config = Config(Map(
"url" -> "my_sql_server.database.windows.net",
"databaseName" -> "my_db_name",
"dbTable" -> "dbo.my_table",
"user" -> "xxxxx",
"password" -> "xxxxx",
"connectTimeout" -> "5", //seconds
"queryTimeout" -> "5" //seconds
))
import org.apache.spark.sql.SaveMode
DF.write.mode(SaveMode.Append).sqlDB(config)
The idea is from this link.
https://docs.databricks.com/data/data-sources/sql-databases-azure.html#connect-to-spark-using-this-library
Everything works fine if I use the original DF headers, as ordinal positions for field names (_c0, _c1, _c2, etc.). I have to have these field names in my table to make this work. Obviously, that's not sustainable. Is there a way to get the DF loaded into a table without matching header names (the order of the fields will always be the same in the DF and the table). Or, is it better way to do this, like renaming the field names of the Spark DF? Thanks.
I found a solution!
val newNames = Seq("ID", "FName", "LName", "Address", "ZipCode", "file_name")
val dfRenamed = df.toDF(newNames: _*)
dfRenamed.printSchema
Almost definitely an XY problem but I can't think of a concise way to phrase what I'm trying to do.
I have a textarea. Inside this text area, the user enters a comma-separated list of ID numbers. When they click "Fetch", I split their input on commas, to get multiple string values, and each of those string values gets passed to a function that makes a HTTP request to my API getting info on the item.
That's where I stumble. Right now I have these parts:
getInfo : String -> Cmd Msg, takes an ID string and ultimately fires Http.send
type Msg = Fetch String, where Fetch idStr -> (model, getInfo idStr)
I sort of want to take my textarea's input and say String.split "," |> List.map (\id -> getInfo id). Except I don't know what to do with the List Msg that would give me, I want to fire each of those msgs off, but Elm doesn't work that way?
While reading I found Cmd.batch, but there's not really any info on it in the docs so I'm not sure if that's what I want or how to use it.
Yes, Cmd.batch can batch multiple cmds into one cmd.
For example (via new message: FetchAll):
FetchAll idsStr ->
let
cmds = String.split "," idsStr |> List.map (\id -> getInfo id)
in (model, Cmd.batch cmds)
also, (model, Cmd.batch cmds) can be written as model ! cmds
Two questions:
How can I find what are the modules that are pre-loaded in my ocaml session?
Given a module, how can I list its contents?
In SML, a standard "trick" was to define a dummy module and open in it a module the contents of which I wanted to inspect. The signature of the dummy module would then list the contents of the module in SML. This does not work in ocaml.
Found this: To see the packages pre-loaded, use #use "topfind";; to use the topfind package, and the #list;; will list the pre-loaded packages!
I don't know a way to list the modules currently loaded.
To show the contents of a module:
# #show_module Pervasives;;
module Pervasives :
sig
external raise : exn -> 'a = "%raise"
external raise_notrace : exn -> 'a = "%raise_notrace"
val invalid_arg : string -> 'a
. . .
val unsafe_really_input : in_channel -> bytes -> int -> int -> unit
val do_at_exit : unit -> unit
end
The initial set of top-level directives is given in Section 9.2 of the OCaml manual.
I want to define the structure of my function input.
This module defines my function (part of it is pseudo code):
-module(my_service).
-export([my_function/2]).
-type my_enum() :: 1 | 2 | 5.
-record(my_record, {id = null :: string(), name = null :: string(), myType = null :: my_enum()}).
-spec my_function(MyValue#my_record) -> Result#my_record.
my_function(ClientRequest, MyValue) when is_record(Entry, my_record) ->
Response = client:request(get, "http://www.example.com/api?value=" + MyValue#my_record.name),
case Response of
{ok, Status, Head, Body} ->
Result = parse_response(Body, my_record);
Error ->
Error
end.
This is how I want to call it:
-module(test1).
-import(io, [format/2]).
main(_) ->
application:start(inets),
MyTestValue = #my_record{name => "test value", myType => 2},
X = my_service:my_function(MyTestValue),
io:format("Response: ~p", [X]).
So, any idea how I can force the type of the function input to be of type my_record?
It's often handy to destructure a record directly in the function argument list, which also forces that argument to have the desired record type. For example, we can slightly modify your my_function/2 like this:
my_function(ClientRequest, #my_record{name=Name}=MyValue) ->
Response = client:request(get, "http://www.example.com/api?value=" ++ Name),
case Response of
{ok, Status, Head, Body} ->
Result = parse_response(Body, MyValue);
Error ->
Error
end.
Note how we're pattern-matching the second parameter MyValue: we're not only asserting that it's a #my_record{} instance, but we're also extracting its name field into the Name variable at the same time. This is handy because we use Name on the first line of the function body. Note that we also keep the parameter name MyValue because we pass it to parse_response/2 within the function body. If we didn't need it, we could instead write the function head like this:
my_function(ClientRequest, #my_record{name=Name}) ->
This would still have the desired effect of forcing the second argument to be of type #my_record{}, and would also still extract Name. If desired, you could extract other fields in a similar manner:
my_function(ClientRequest, #my_record{name=Name, id=Id}) ->
Both Name and Id are then available for use within the function body.
One other thing: don't use the atom null as a default for your record fields. The default for Erlang record fields is the atom undefined, so you should just use that. This is preferable to defining your own concept of null in the language.
I'm trying to create a many to many table using Groundhog in Haskell, which basically looks like this if I cut away all the other logic I have:
data FooRow = FooRow {
fooRowUUID :: UUID
}
deriving instance Show FooRow
data BarRow = BarRow {
barRowUUID :: UUID
}
deriving instance Show BarRow
data FooToBarRow = FooToBarRow {
fooToBarRowUUID :: UUID,
fooToBarRowFoo :: DefaultKey FooRow,
fooToBarRowBar :: DefaultKey BarRow
}
deriving instance Show FooToBarRow
Now, trying to define operations, I can get and insert all of these records just fine, however I'm not sure how to go from having a FooRow, with it's ID, and then get all the related BarRows by way of the many to many table. Right now I've played with something like this:
getBarsForFoo fooID = do
barKeys <- project
(FooToBarRowBarField)
(FooToBarRowFooField ==. (Foo_FooKey fooID))
select $ (BarRowUUIDField `in_` barKeys)
However this doesn't typecheck, with the error:
Couldn't match type 'UUID' with 'BarRow'
Inspecting just the results of the project with putStrLn, I can see that the type of barKeys is:
[Bar_BarKey UUID]
but I don't quite understand how to make use of that within my query. I don't see any examples like this in the Groundhog documentation, so I'm hoping someone will be able to put me on the right path here.
I'm quite certain there are more efficient ways to go about this (there's going to be a bunch of underlying queries with this approach), but this does at at least get the job done for now.
getBarsForFoo fooID = do
barKeys <- project
(FooToBarRowBarField)
(FooToBarRowFooField ==. (Foo_FooKey fooID))
q <- mapM (getBy) barKeys
return (catMaybes q :: [BarRow])