How to encode tuple to JSON in elm - json

I have tuple of (String,Bool) that need to be encoded to JSON Array in elm.
This below link is useful for the primitive types and other list, array and object. But I need to encode tuple2.
Refer : http://package.elm-lang.org/packages/elm-lang/core/4.0.3/Json-Encode#Value
I tried different approach like encoding tuple with toString function.
It does not gives me JSON Array instead it produces String as below "(\"r"\,False)".
JSON.Decoder expecting the input paramater to decode as below snippet.
decodeString (tuple2 (,) float float) "[3,4]"
Refer : http://package.elm-lang.org/packages/elm-lang/core/4.0.3/Json-Decode
Q : When there is decode function available for tuple2, why encode function is missing it.

You can build a generalized tuple size 2 encoder like this:
import Json.Encode exposing (..)
tuple2Encoder : (a -> Value) -> (b -> Value) -> (a, b) -> Value
tuple2Encoder enc1 enc2 (val1, val2) =
list [ enc1 val1, enc2 val2 ]
Then you can call it like this, passing the types of encoders you want to use for each slot:
tuple2Encoder string bool ("r", False)

In elm 0.19 https://package.elm-lang.org/packages/elm/json/latest/Json-Encode a generalized tuple 2 encoder would be
import Json.Encode exposing (list, Value)
tuple2Encoder : ( a -> Value ) -> ( b -> Value ) -> ( a, b ) -> Value
tuple2Encoder enc1 enc2 ( val1, val2 ) =
list identity [ enc1 val1, enc2 val2 ]
Usage:
encode 0 <| tuple2Encoder string int ("1",2)

Related

How to make tail function return what I need?

I need to encode list in OCaml. Command: encode ['a','a','b','b','b','c'];; have to return [(2,'a');(3,'b');(1,'c')]
Now I have this function:
let encode list =
let rec encodeHelper list acc = match list with
| [] -> []
| head :: [] -> (1, head) :: []
| head :: headNext :: tail -> if (head = headNext) then encodeHelper (headNext :: tail) (acc + 1)
else (acc, head) :: encodeHelper (headNext :: tail) acc
in encodeHelper list 1
;;
But it returns:
: (int * (char * char * char * char * char * char)) list =
[(1, ('a', 'a', 'b', 'b', 'b', 'c'))]
Your test data as shown at the top is not in the right form.
A list in OCaml has elements separated by semicolons (;). Your test data is using commas instead (,). Commas are used for tuples, which is why you're seeing a tuple in your result.
If you change , to ; in your test data you should see something closer to what you're looking for. There is at least one problem left to fix (in my testing).

Is it possible to write a recursive grouping function like this in f#

Lets say you had a requirement to group a sequence into a sequence of tuples. Each tuple is a key*seq. So in a sense, the result is a sequence of sequences.
All pretty standard so far.
What if you wanted to further group each sub sequence by some other key? It would be easy enough to map another groupby function onto each element of your sequence of sequences. You would then have a sequence of sequences of sequences.
Starting to get slightly hairy.
What if you wanted to group it even further?
Would it be possible to write a function that can take in a key generating function and an arbitrary sequence, and recursively unwraps the layers and then adds another layer of grouping using the keyFunction?
I suspect the answer is no, because the recursive function would not have a well defined type.
My attempt at this, to further illustrate the idea:
let rec recursiveGrouper keyFunction aSeq =
let first = Seq.head aSeq
match first with
| ((a:'a), _) -> Seq.map (fun (b,(c:seq<'c>)) -> (b, recursiveGrouper keyFunction c)) aSeq
| _ -> Seq.groupBy keyFunction aSeq
EDIT:
Lets add an example of how this might work, it it were possible
type FruitRecord = {Fruit:string; Number:int; SourceFarm:string; Grade:float}
let key1 fr =
fr.Fruit
let key2 fr =
fr.SourceFarm
let key3 fr =
match fr.Grade with
|f when f > 5.0 -> "Very Good"
|f when f > 2.5 -> "Not bad"
|_ -> "Garbage"
Lets say we have a whole bunch of fruit records in a sequence. We want to group them by type of fruit.
One way would be to say
let group1 = fruitRecs |> Seq.groupBy key1
Using our recursive function, this would be
let group1 = recursiveGrouper key1 fruitRecs
Next, lets say we want to group each of the items in the groups of group1 by source farm.
We could say
let group2 =
group1
|> Seq.map (fun (f, s) -> (f, Seq.groupBy key2 s))
Using our recursive function it would be
let group2 = recursiveGrouper key2 group1
And we could go further and group by Grade by saying
let group3 = recursiveGrouper key3 group2
Actually there are some ways to make that recursive function work, using static constraints. Here's a small example:
// If using F# lower than 4.0, use this definition of groupBy
module List =
let groupBy a b = Seq.groupBy a (List.toSeq b) |> Seq.map (fun (a, b) -> a, Seq.toList b) |> Seq.toList
type A = class end // Dummy type
type B = class end // Dummy type
type C =
inherit B
static member ($) (_:C, _:A ) = fun keyFunction -> () // Dummy overload
static member ($) (_:C, _:B ) = fun keyFunction -> () // Dummy overload
static member ($) (_:B, aSeq) = fun keyFunction -> List.groupBy keyFunction aSeq // Ground case overload
static member inline ($) (_:C, aSeq) = fun keyFunction -> List.map (fun (b, c) -> b, (Unchecked.defaultof<C> $ c) keyFunction) aSeq
let inline recursiveGrouper keyFunction aSeq = (Unchecked.defaultof<C> $ aSeq) keyFunction
// Test code
type FruitRecord = {Fruit:string; Number:int; SourceFarm:string; Grade:float}
let key1 fr = fr.Fruit
let key2 fr = fr.SourceFarm
let key3 fr =
match fr.Grade with
|f when f > 5.0 -> "Very Good"
|f when f > 2.5 -> "Not bad"
|_ -> "Garbage"
let fruitRecs = [
{Fruit = "apple" ; Number = 8; SourceFarm = "F"; Grade = 5.5}
{Fruit = "apple" ; Number = 5; SourceFarm = "F"; Grade = 4.5}
{Fruit = "orange"; Number = 8; SourceFarm = "F"; Grade = 5.5}
]
let group1 = recursiveGrouper key1 fruitRecs
let group2 = recursiveGrouper key2 group1
let group3 = recursiveGrouper key3 group2
I don't think you could write it as a recursive function with the sort of constraints you put on yourself - that is:
A tuple 'key * seq<'value> representing the grouping,
A heterogeneous key function (or a collection thereof) - this is what I understand by "group each sub sequence by some other key".
You could make some leeway if you would represent the grouping as an actual tree type (rather than an ad-hoc tree built from tuples) - that way you'd have a well-defined recursive result type to go with your recursive function.
If at that point you would be able to also compromise on the key function to make it homogeneous (worst case - producing a hashcode), you should be able to express what you want within the type system.
You certainly could have a non-recursive grouping function that takes a grouped sequence and puts another level of grouping on top of it - like the one below:
module Seq =
let andGroupBy (projection: 't -> 'newKey) (source: seq<'oldKey * seq<'t>>) =
seq {
for key, sub in source do
let grouped = Seq.groupBy projection sub
for nkey, sub in grouped do
yield (key, nkey), sub
}
Using your FruitRecord example:
values
|> Seq.groupBy key1
|> Seq.andGroupBy key2
|> Seq.andGroupBy key3

Haskell - Couldn't match expected type ‘JValue’ with actual type ‘[(String,JValue)]’

I'm new to Haskell and I have a problem with JValue, I previously defined it as:
data JValue =
JString String
| JNumber Double
| JBool Bool
| JNull
| JObject [(String, JValue)]
| JArray [JValue]
And I'm trying to make a function
getPosition :: String -> JValue -> Int -> Int
getPosition _ (JObject []) _ = -1
getPosition word (JObject [(name,_)]) index
| stringsAreEqual word name = index
| otherwise = -1
getPosition word (x:xs) index = getPosition word xs (index+1)
that is intended to find the index of a tuple in a JObject that has the same string as the one in the arguments. I'm getting this error:
Couldn't match expected type ‘with actual type ‘[(String, JValue)]’
What am I doing wrong? I may be complicating myself too much. Thanks
In the 2nd argument of the last clause, you pattern match against a list (x:xs), but there must be a JValue.
When you want to find the index in a list, use findIndex from Data.List
getPosition word (JObject tuples) =
findIndex (\(name,_) -> name == word) tuples

Retriving a value from Array of Vector Value

I have the following code:
case (HashMap.lookup "key123" jsnObj) of
Just c ->
case c of
Array d -> print d
and the result:
fromList [String "123.00000",String "0.456789"]
I can't figure out how I can retrieve the second value from it. Your suggestions?
You need to have Data.Vector imported and then you can simply use the indexing function ! on the Vector d:
case HashMap.lookup "key123" jsnObj of
Just c -> case c of
Array d -> print $ d ! 1

SML - Creating dictionary that maps keys to values

I need to create a dictionary in sml, but I am having extreme difficulty with an insert function.
type dict = string -> int option
As an example, here is the empty dictionary:
val empty : dict = fn key => NONE
Here is my implementation of an insert function:
fun insert (key,value) d = fn d => fn key => value
But this is of the wrong type, what I need is insert : (string*int) -> dict -> dict.
I've searched everything from lazy functions to implementing dictionaries.
Any help or direction would be greatly appreciateds!
If you are still confused on what I am trying to implement, I drafted up what I should expect to get when calling a simple lookup function
fun lookup k d = d k
- val d = insert ("foo",2) (insert ("bar",3) empty);
val d = fn : string -> int option
- lookup2 "foo" d;
val it = SOME 2 : int option
- lookup2 "bar" d;
val it = SOME 3 : int option
- lookup2 "baz" d;
val it = NONE : int option
You can reason on the signature of the function:
val insert = fn: (string * int) -> dict -> dict
When you supply key, value and a dictionary d, you would like to get back a new dictionary d'. Since dict is string -> int option, d' is a function takes a string and returns an int option.
Suppose you supply a string s to that function. There are two cases which could happen: when s is the same as key you return the associated value, otherwise you return a value by looking up d with key s.
Here is a literal translation:
fun insert (key, value) d = fn s => if s = key then SOME value
else d s