I have a NameValueCollection which I need to convert to a Map and I just can't work it out. I tried:
let headerMap (m : MailMessage) = m.Headers |> Map.map (fun k v -> v.[k])
Do I need to use Seq.map instead?
Basically the point of this is that I want to serialize the headers in a System.Net.MailMessage to JSON.
Daniel's answer will work just fine, but I thought I'd offer some additional alternatives:
Array.fold -- This should be faster than Daniel's version since it avoids the overhead of the iterators.
let mapOfNameValueCollection (collection : NameValueCollection) =
(Map.empty, collection.AllKeys)
||> Array.fold (fun map key ->
let value = collection.[key]
Map.add key value map)
Array.fold with sets of values -- Similar to the code above, but returns the value as a Set<string> which may be useful if you want to determine if some value is in the returned set of values.
let mapOfNameValueCollection (collection : NameValueCollection) =
(Map.empty, collection.AllKeys)
||> Array.fold (fun map key ->
let valueSet =
match collection.[key] with
| null ->
Set.empty
| values ->
Set.ofArray <| values.Split [| ',' |]
Map.add key valueSet map)
Recursive loop -- Creates the map item-by-item with a recursive loop. I wouldn't use this in practice because the Array.fold version would be easier and faster. However, this approach could be faster if the specific collection class you're using (derived from NameValueCollection) overrides the AllKeys property and has some weird internal behavior which takes a long time to return the property value.
let mapOfNameValueCollection (collection : NameValueCollection) =
let rec createMap map idx =
if idx < 0 then map
else
let itemName = collection.GetKey idx
let itemValue = collection.[itemName]
let map = Map.add itemName itemValue map
createMap map (idx - 1)
createMap Map.empty (collection.Count - 1)
Imperative loop -- Creates the map item-by-item with an imperative loop. As with the recursive loop, I'd prefer to use Array.fold in practice unless there was some special reason not to.
let mapOfNameValueCollection (collection : NameValueCollection) =
let mutable map = Map.empty
let maxIndex = collection.Count - 1
for i = 0 to maxIndex do
let itemName = collection.GetKey i
let itemValue = collection.[itemName]
map <- Map.add itemName itemValue map
map
nvc.AllKeys
|> Seq.map (fun key -> key, nvc.[key])
|> Map.ofSeq
Related
I am trying to implement some graph algorithms with the OCaml language.
I've made a graph type with a two dimension array which refer to the graph I want to use
And here is my function to get the list of all the point linked to a v point :
let voisins graphe v =
let rec voisinsAux tableau i res =
if i = Array.length tableau then
res
else if v != i then
voisinsAux tableau (i + 1) (ajouter res (Array.get tableau i))
else
voisinsAux tableau (i + 1) res
in voisinsAux (Array.get graphe.matrice v) 0
;;
I guess it's not clean but I think it's OK.
The problem is when I test it, I'm getting this:
let listeVoisins = voisins g 3;;
val listeVoisins : int list -> int list = <fun>
How can I get a fun type since voisins g 3 should be an int list type expression?
Why my listeVoisins is not executed as an expression?
Functions in OCaml are curried. We have syntax that lets us work with the concept more conveniently, but a function takes a single value and returns a single value.
Of course, functions are values, so a function can return another function which in turn takes an argument and returns something. The function it can return has access to every value that was in scope when it was created. Research "closures."
Consider your code, with the inner function rewritten to reflect this:
let voisins graphe v =
let rec voisinsAux =
fun tableau ->
fun i ->
fun res ->
if i = Array.length tableau then
res
else if v != i then
voisinsAux tableau (i + 1) (ajouter res (Array.get tableau i))
else
voisinsAux tableau (i + 1) res
in voisinsAux (Array.get graphe.matrice v) 0
That is not pretty to look at, but it's functionally the same as what you wrote.
You've then only applied two arguments to voisinsAux which takes three. This means what you've gotten back is a function that takes one argument (res - apparently an int list) and then calculates the int list result you're looking for.
I am really wanting to use Dhall lang to solve an issue that I have with using the Github Terraform Provider.
See: https://github.com/etaty/example-dhall-terraform-github
However, I have never used Dhall before and really only have this one use case for using it.
I am wanting to debug the errors that I am getting in this github repo to create the github.tf file.
The error that I get is as follows:
Error: Invalid type for ❰List❱
63│ [] : Optional (List a)
64│
I have included line 63 below and where this error is being referenced. I went online to do alot of research around this however, I have not had any success.
in let emptyListToOptional = \(a: Type) -> \(l: List a) ->
if (null a l) then [] : List Natural , Optional (List a)
else [l] : List Natural, Optional (List a)
in let build = \(config: T.Config) ->
let github_membership = map T.GithubUser T.TF/GithubMembership makeGithubMembership config.users
in let github_team = map T.Team T.TF/GithubTeam makeGithubTeam config.teams
in let github_team_membership = concat T.TF/GithubTeamMembership (map T.GithubUser (List T.TF/GithubTeamMembership) makeGithubTeamMembership config.users)
in {
github_membership = emptyListToOptional T.TF/GithubMembership github_membership
, github_team = emptyListToOptional T.TF/GithubTeam github_team
, github_team_membership = emptyListToOptional T.TF/GithubTeamMembership github_team_membership
}
in {
Any Help Would Be Greatly Appreciated!
The code you linked to is out of date; the way you specify Optional values has changed. For instance, the lines
in let emptyListToOptional = \(a: Type) -> \(l: List a) ->
if (null a l) then [] : List Natural , Optional (List a)
else [l] : List Natural, Optional (List a)
were originally (from the repository)
in let emptyListToOptional = \(a: Type) -> \(l: List a) ->
if (null a l) then [] : Optional (List a)
else [l]: Optional (List a)
which should now read
in let emptyListToOptional = \(a: Type) -> \(l: List a) ->
if (null a l) then None (List a)
else Some l
I want to decode json string like below.
"[[\"aaa\",1,2,3,4],[\"bbb\",1,2,3]]"
and decode to Elm tuple list.
[("aaa",[1,2,3,4]),("bbb",[1,2,3])] : List (String, List Int)
How to decode it?
jsdecode=index 0 string
|> andThen xxxxxxx??
This isn't straightforward to do, but before I jump straight in how to do it, let me collect a series of thoughts about the data we are trying to decode:
We are decoding a list of lists
Each list should be composed by a starting string and a series of values
But actually there might be an empty list, no initial string but some values or an initial string and no values
So in my mind the difficulty of building the right decoder reflects the complexity of handling all these edge cases. But let's start defining the data we would like to have:
type alias Record =
( String, List Int )
type alias Model =
List Record
jsonString : String
jsonString =
"[[\"aaa\",1,2,3,4],[\"bbb\",1,2,3]]"
decoder : Decoder Model
decoder =
Decode.list recordDecoder
Now we need to define a type that represents that the list could contain either strings or ints
type EntryFlags
= EntryId String
| EntryValue Int
type RecordFlags
= List EntryFlags
And now for our decoder
recordDecoder : Decoder Record
recordDecoder =
Decode.list
(Decode.oneOf
[ Decode.map EntryId Decode.string
, Decode.map EntryValue Decode.int
]
)
|> Decode.andThen buildRecord
So buildRecord takes this list of EntryId String or EntryValue Int and builds the record we are looking for.
buildRecord : List EntryFlags -> Decoder Record
buildRecord list =
case list of
[] ->
Decode.fail "No values were passed"
[ x ] ->
Decode.fail "Only key passed, but no values"
x :: xs ->
case buildRecordFromFlags x xs of
Nothing ->
Decode.fail "Could not build record"
Just value ->
Decode.succeed value
As you can see, we are dealing with a lot of edge cases in our decoder. Now for the last bit let's check out buildRecordFromFlags:
buildRecordFromFlags : EntryFlags -> List EntryFlags -> Maybe Record
buildRecordFromFlags idEntry valueEntries =
let
maybeId =
case idEntry of
EntryId value ->
Just value
_ ->
Nothing
maybeEntries =
List.map
(\valueEntry ->
case valueEntry of
EntryValue value ->
Just value
_ ->
Nothing
)
valueEntries
|> Maybe.Extra.combine
in
case ( maybeId, maybeEntries ) of
( Just id, Just entries ) ->
Just ( id, entries )
_ ->
Nothing
In this last bit, we are using a function from maybe-extra to verify that all the values following the initial EntryId are indeed all of the EntryValue type.
You can check out a working example here: https://ellie-app.com/3SwvFPjmKYFa1
There are two subproblems here: 1. decoding the list, and 2. transforming it to the shape you need. You could do it as #SimonH suggests by decoding to a list of JSON values, post processing it and then (or during the post-processing) decode the inner values. I would instead prefer to decode it fully into a custom type first, and then do the post processing entirely in the realm of Elm types.
So, step 1, decoding:
type JsonListValue
= String String
| Int Int
decodeListValue : Decode.Decoder JsonListValue
decodeListValue =
Decode.oneOf
[ Decode.string |> Decode.map String
, Decode.int |> Decode.map Int
]
decoder : Decode.Decoder (List (List JsonListValue))
decoder =
Decode.list (Decode.list decodeListValue)
This is a basic pattern you can use to decode any heterogenous array. Just use oneOf to try a list of decoders in order, and map each decoded value to a common type, typically a custom type with a simple constructor for each type of value.
Then onto step 2, the transformation:
extractInts : List JsonListValue -> List Int
extractInts list =
list
|> List.foldr
(\item acc ->
case item of
Int n ->
n :: acc
_ ->
acc
)
[]
postProcess : List JsonListValue -> Result String ( String, List Int )
postProcess list =
case list of
(String first) :: rest ->
Ok ( first, extractInts rest )
_ ->
Err "first item is not a string"
postProcess will match the first item to a String, run extractInts on the rest, which should all be Ints, then put them together into the tuple you want. If the first item is not a String it will return an error.
extractInts folds over each item and adds it to the list if it is an Int and ignores it otherwise. Note that it does not return an error if an item is not an Int, it just doesn't include it.
Both of these functions could have been written to either fail if the values don't conform to the expectations, like postProcess, or to handle it "gracefully", like extractInts. I chose to do one of each just to illustrate how you might do both.
Then, step 3, is to put it together:
Decode.decodeString decoder json
|> Result.mapError Decode.errorToString
|> Result.andThen
(List.map postProcess >> Result.Extra.combine)
Here Result.mapError is used to get error from decoding to conform to error type we get from postProcess. Result.Extra.combine is a function from elm-community/result-extra which turns a List of Results into a Result of List, which comes in very handy here.
For all the progress I've made in F#, I still get lost in various of the constructor and deconstructor syntax.
I'm running a recursive simulation. One of the parameters is a function for the stopping condition. I have various possible stopping conditions to choose from. I make them all have the same signature. So I decide it would be nice, and educational, to lock down these functions to a custom type--so that not just any function that happens to match the signature can be sent:
type StoppingCondition = | StoppingCondition of (ReturnType -> ReturnType -> int -> float -> bool)
I think I'm doing this right, from tutorials, having a type name and an identical constructor name (confusing...), for a single case discriminated union. But now I can't figure out how to apply this type to an actual function:
let Condition1 lastRet nextRet i fl =
true
How do I make Condition1 be of type StoppingCondition? I bet it's trivial. But I've tried putting StoppingCondition as the first, second or last term after let, with and without parens and colons. And everything is an error.
Thanks for the patience found here.
EDIT:
I'll try to synthesize what I lean from the four answers (as of this moment), all good:
Trying to mimic this pattern:
s : string = "abc"
I was trying to write:
type StoppingCondition = | StoppingCondition of (ReturnType -> ReturnType -> int -> float -> bool)
let condition1 lastRet nextRet i fl : StoppingCondition = // BAD
//wrong for a type alias, totally wrong for a union constructor
true
//or
let condition1 : StoppingCondition lastRet nextRet i fl = // BAD again
true
or other insertions of : Stopping Condition (trying to prefix it, in the way that constructors go, in that one line).
Now I see that to get what I was getting at I would have to do:
type StoppingCondition = | StoppingCondition of (ReturnType -> ReturnType -> int -> float -> bool)
let conditionFunc1 lastRet nextRet i fl = //...
true
let stoppingCondition1 = StoppingCondition conditionFunc1
//or
let stoppingCondition2 = StoppingCondition <| (func lastRet nextRet i fl -> false)
//and there's another variation or 2 below
And what I didn't appreciate as a big negative to this approach is how a union type is different from a type alias. A type alias of string admits of the string functions when declared--it really is a string and does "string things. A single case discriminated union of string--is not a string any more. To have it do "string things" you have to unwrap it. (Or write versions of those functions into your type (which might be wrappers of the string functions).) Likewise a type alias of my function accepts those parameters. A DU of my function is just a wrapper and doesn't take arguments. So this doesn't work with discriminated union:
let x = stoppingCondition1 ret1 ret2 2 3.0 // BAD
//"stoppingCondition1 is not a function and cannot be applied"
And there's not enough value in my case here to work around the wrapper. But a type alias works:
type StoppingAlias = ReturnType -> ReturnType -> int -> float -> bool
let stoppingCondition:StoppingAlias = fun prevRet nextRet i x -> true
let b = stoppingCondition ret1 ret2 10 1.0 // b = true
I may not have everything straight in what I just said, but I think I'm a lot closer.
Edit 2:
Side note. My question is about defining the type of a function. And it compares using a type alias and a union type. As I worked at trying to do these, I also learned this about using a type alias:
This works (from: https://fsharpforfunandprofit.com/posts/defining-functions/ ):
type Adder = decimal -> decimal -> decimal
let f1 : Adder = (fun x y -> x + y)
//or
let f2 : decimal -> decimal -> decimal = fun x y -> x + y
but these are wrong:
let (f2 : Adder) x y = x + y // bad
let (f3 x y) : (decimal -> decimal -> decimal) = x + y // bad
let (f3 : (decimal -> decimal -> decimal)) x y = x + y // bad
And some discussion on this whole issue: F# Type declaration possible ala Haskell?
(And also, yeah, "assigning a type" isn't the right thing to say either.)
You don't "make it be of type" StoppingCondition. You declare a value of type StoppingCondition and pass Condition1 as the parameter of the DU case constructor:
let stop = StoppingCondition Condition1
That means, however, that every time you want to access the function contained in your single DU case, you have to pattern match over it in some way; that can become annoying.
You say you don't want just any functions that fulfill the signature to be valid as stopping conditions; however, it seems to be specific enough to avoid "accidentally" passing in an "inappropriate" function - with that, you could do something simpler - define StoppingCondition as a type alias for your specific function type:
type StoppingCondition = ReturnType -> ReturnType -> int -> float -> bool
Now you can use StoppingCondition everywhere you need to specify the type, and the actual values you pass/return can be any functions that fulfill the signature ReturnType -> ReturnType -> int -> float -> bool.
As has been said, you have to construct an instance of a StoppingCondition from an appropriate function, for example:
let Condition1 = StoppingCondition (fun _ _ _ _ -> true)`
One nice way to do this without weird indentation or extra parentheses is a backward pipe:
let Condition1 = StoppingCondition <| fun lastRet nextRet i fl ->
// Add function code here
The signature might be long enough to justify a record type instead of four curried parameters. It's a question of style and how it'll be used; the result may look like this:
type MyInput =
{ LastReturn : ReturnType
NextReturn : ReturnType
MyInt : int
MyFloat : float }
type StopCondition = StopCondition of (MyInput -> bool)
let impossibleCondition = StopCondition (fun _ -> false)
let moreComplicatedCondition = StopCondition <| fun inp ->
inp.MyInt < int (round inp.MyFloat)
To call the function inside a StopCondition, unwrap it with a pattern:
let testStopCondition (StopCondition c) input = c input
Specify the return type of a function is done like this:
let Condition1 lastRet nextRet i fl :StoppingCondition=
true
of course, this won't compile as true is not of the correct type.
I suspect the actual definition you want is closer to
let Condition1 :StoppingCondition=
true
though, as the type looks like it contains the function arguments.
Expanding on this, you can define such a function like:
let Condition1=fun a b c d -> StoppingCondition(fun a b c d -> whatever)
but this whole thing is pretty ugly.
Realistically, I think it is better to put all the functions in an array, which will force the types to match
So, it seems to me that you things you might want to with StoppingConditions are to create some predefined type of stopping condition.
Here are some examples of some possible stopping conditions:
let stopWhenNextGreaterThanLast = StoppingCondition (fun last next _ _ -> next > last)
let stopWhenLastGreaterThanLast = StoppingCondition (fun last next _ _ -> last> next)
(I've underscored the parameters I'm not using in my stopping condition definition)
Hopefully you can see that both of these values of type StoppingCondition.
Then you might want a function to determine if the stopping condition had been met given some parameters:
let shouldStop stoppingCond last next i value =
match stoppingCond with
|StoppingCondition f -> f last next i value
This function takes a stopping condition and the various states of your recursion and returns true or false depending on whether or not it should now stop.
This should be all you need to make use of this approach in practice.
You could extend this approach by doing something like this to cover multiple potential stopping conditions:
type StoppingCondition =
| StoppingCondition of (ReturnType -> ReturnType -> int -> float -> bool)
| Or of StoppingCondition * StoppingCondition
And modifying the shouldStop function
let rec shouldStop stoppingCond last next i value =
match stoppingCond with
|StoppingCondition f -> f last next i value
|Or (stp1, stp2) -> (shouldStop stp1 last next i value) || (shouldStop stp2 last next i value)
Now if we have a single condition, we stop when it's met or if we multiple conditions, we can check whether either of them are met.
Then you could Or together new stopping conditions from a base condition:
let stopWhenIIsEven = StoppingCondition (fun _ _ i _ -> i % 2 = 0)
let stopWhenValueIsZero = StoppingCondition (fun _ _ _ value -> value = 0.0)
let stopWhenIEvenOrValueZero = Or (stopWhenIIsEven, stopWhenValueIsZero)
I'm trying to grab data from a MySQL database.
Approach 2 - apply/map style
I'm using the MySQL ADO Reference to try to build this system. In particular, the example found at 21.2.3.1.7.
(using a pseudo code)
let table = build_sequence(query.read)
Where query.read returns a row in the table(Or rather, a list of elements that happen to be a row in the table). And the table variable is a list of lists that will represent a table returned from the query.
I've stared at the code given below, and it's syntax is over my head, I'm afraid.
Approach 1 - looping.
Problem 1: It's inelegant, requiring a mutable.
Problem 2: This just feels wrong, based on my prior experience with Prolog & Lisp. There's gotta be a more...functional way to do this.
I'm not sure where to begin though. Comments & thoughts?
let reader : MySql.Data.MySqlClient.MySqlDataReader = command.ExecuteReader()
let arr = []
let mutable rowIter = 0
let readingLoop() =
while(reader.Read()) do
rowIter = rowIter + 1
for i = 0 to reader.FieldCount do
//set arr[someiterator, i] = reader.GetValue[i].ToString())
The Seq type has a neat function for handling database cursors called generate_using (see F# Manual and the Data Access chapter in Foundations of F#). This is a higher order function that takes one function to open the cursor and another (called repeatedly) to process records from the cursor. Here is some code that uses generate_using to execute a sql query:
let openConnection (connectionName : string) =
let connectionSetting = ConfigurationManager.ConnectionStrings.Item(connectionName)
let connectionString = connectionSetting.ConnectionString
let connection = new OracleConnection(connectionString)
connection.Open()
connection
let generator<'a> (reader : IDataReader) =
if reader.Read() then
let t = typeof<'a>
let props = t.GetProperties()
let types = props
|> Seq.map (fun x -> x.PropertyType)
|> Seq.to_array
let cstr = t.GetConstructor(types)
let values = Array.create reader.FieldCount (new obj())
reader.GetValues(values) |> ignore
let values = values
|> Array.map (fun x -> match x with | :? DBNull -> null | _ -> x)
Some (cstr.Invoke(values) :?> 'a)
else
None
let executeSqlReader<'a> (connectionName : string) (sql : string) : 'a list =
let connection = openConnection connectionName
let opener() =
let command = connection.CreateCommand(CommandText = sql, CommandType = CommandType.Text)
command.ExecuteReader()
let result = Seq.to_list(Seq.generate_using opener generator)
connection.Close()
connection.Dispose()
result
For example to list all the tables in an Oracle database we need to define a column definition type and invoke executeSqlReader as follows:
type ColumnDefinition = {
TableName : string;
ColumnName : string;
DataType : string;
DataLength : decimal;
}
let tableList = executeSqlReader<ColumnDefinition>
"MyDatabase"
"SELECT t.table_name, column_name, data_type, data_length FROM USER_TABLES t, USER_TAB_COLUMNS c where t.TABLE_NAME = c.table_name order by t.table_name, c.COLUMN_NAME"
It can be hard to work with imperative APIs in a non-imperative way. I don't have MySql handy, but I made an approxmiation, hopefully this will provide inspiration. Seq.unfold is a function people find pretty awesome once they grok it. List.init (or Array.init) are also handy for initializing known-size data structures without using mutables.
#light
type ThingLikeSqlReader() =
let mutable rowNum = 0
member this.Read() =
if rowNum > 3 then
false
else
rowNum <- rowNum + 1
true
member this.FieldCount = 5
member this.GetValue(i) = i + 1
let reader = new ThingLikeSqlReader()
let data = reader |> Seq.unfold (fun (reader : ThingLikeSqlReader) ->
if reader.Read() then
Some (List.init reader.FieldCount (fun i -> reader.GetValue(i)), reader)
else
None) |> Seq.to_list
printfn "%A" data