In below select_highest_bids function, is it better to use orddict:new() instead of list, something like below ?
OrderedBatches = lists:foldl(fun high_bid_filter/2, orddict:new(), Campaigns)
How can we change high_bid_filter to return orddict ?
select_highest_bids(Campaigns, BidRequest) ->
lists:map(fun({_, C}) -> C end,
lists:foldl(fun high_bid_filter/2, [], Campaigns),
high_bid_filter(Campaign = #campaign_response{bid = BR = #bid_response{ad_id = AdID, cpm_bid = Score}}, Campaigns) ->
case lists:keyfind(AdID, 1, Campaigns) of
false ->
[{AdID, Campaign}|Campaigns];
{AdID, _ = #campaign_response{bid = _ = #bid_response{cpm_bid = EB}}} when EB >= Score ->
Campaigns;
{AdID, _ = #campaign_response{bid = _ = #bid_response{cpm_bid = EB}}} when EB < Score ->
lists:keystore(AdID, 1, Campaigns, {AdID, Campaign})
end.
here is the folder function
high_bid_filter(Campaign = #campaign_response{bid = #bid_response{ad_id = AdID, cpm_bid = Score}}, Campaigns) ->
case orddict:take(AdID, Campaigns) of
{V, _} when V >= Score ->
% find value but higher than Offer
Campaigns;
{V, Dict} ->
% update higher value
orddict:store(AdID, Campaign, Dict);
error ->
%
orddict:store(AdID, Campaign, Campaigns)
end.
i hope it can help you
Related
Nested F# Record with generic type parameter, how do I statically cast between types in nested structure equivalent to traversing and performing 'T |> 'K, e.g. float |> int?
Currently I am Naively traversing the nested records and explicitly converting the type with from:float |> to:int or equivalently int(from). However, this is not very beautiful.
type Person<'T> = {Id : int; Value : 'T}
type Family<'T> = {Id : 'T; People : seq<Person<'T>>}
let fam1 = {Id = 1.0; People = [{Id = 1.1; Value = 2.9}; {Id = 1.2; Value = 4.4}]} : Family<float>
let fam2 = {Id = 2.0; People = [{Id = 2.1; Value = 3.9}; {Id = 2.2; Value = 5.4}]} : Family<float>
let partyFloat = seq{ yield fam1; yield fam2}
// In general, how to do this from a type T to a type K where conversion using T |> K will work
let partyInt : seq<Family<int>> = partyFloat
How to statically and/or
lazily convert to seq<Family<int>>?
In my real world case I have a DiffSharp D type that can be converted to a float with D |> float or float(D).
There is no magic way to cast the insides of types, you have to write your own.
It is idiomatic for F# and functional programming in general (and I personally recommend it, too) to write small functions for simple data transformations, and then assemble them together:
let mapPerson f p = { Id = p.Id; Value = f p.Value }
let mapFamily f fm = { Id = f fm.Id; People = Seq.map (mapPerson f) fm.People }
let mapParty f = Seq.map (mapFamily f)
let partyInt = mapParty int partyFloat
But of course you can do it in one big messy go:
let partyInt =
partyFloat
|> Seq.map (fun fm ->
{ Id = int fm.Id
People =
fm.People
|> Seq.map (fun p ->
{ Id = p.Id; Value = int p.Value }
)
}
)
It seems like what you are asking for are covariance ie that this should compile
let vs : obj list = ["1"; "2"]
F# doesn't support covariance (or contravariance) and probably never will. C# does however so you could write something like this
using System.Collections.Generic;
interface IPerson<out T>
{
int Id { get; }
T Value { get; }
}
interface IFamily<out T>
{
int Id { get; }
IEnumerable<IPerson<T>> Members { get; }
}
static class Program
{
static IFamily<string> CreateFamily()
{
return null;
}
static void Main(string[] args)
{
IFamily<string> familyOfString = CreateFamily();
IFamily<object> familyOfObject = familyOfString;
}
}
However, there's a functional pattern that could help us called polymorphic lenses.
(Picture from reddit thread: https://www.reddit.com/r/haskell/comments/2qjnho/learning_curves_for_different_programming/)
I used to think that polymorphic lenses isn't possible in F# due to the lack of higher-rank types. However, there's a hidden gem out there: http://www.fssnip.net/7Pk
Vesa Karvonen (IIRC he is also behind hopac so he's pretty cool) implements polymorphic lenses in F# using some pretty interesting tricks.
We can then map the inner values of an immutable structure reasonably easy.
let input : Family<int> =
{
Id = 1
Members = [{ Id = 10; Value = 123}; { Id = 11; Value = 456}]
}
printfn "%A" input
let output : Family<string> =
input
|> over Family.membersL (overAll Person.valueL ((+) 1 >> string))
printfn "%A" output
Full source code
// ----------------------------------------------------------------------------
// The code below taken from: http://www.fssnip.net/7Pk
// by Vesa+Karvonen - http://www.fssnip.net/authors/Vesa+Karvonen
// ----------------------------------------------------------------------------
type LensFunctor<'a> =
| Over of 'a
| View
member t.map a2b =
match t with
| Over a -> Over (a2b a)
| View -> View
type Lens<'s,'t,'a,'b> = ('a -> LensFunctor<'b>) -> 's -> LensFunctor<'t>
module Lens =
let view l s =
let r = ref Unchecked.defaultof<_>
s |> l (fun a -> r := a; View) |> ignore
!r
let over l f =
l (f >> Over) >> function Over t -> t | _ -> failwith "Impossible"
let set l b = over l <| fun _ -> b
let (>->) a b = a << b
let lens get set = fun f s ->
(get s |> f : LensFunctor<_>).map (fun f -> set f s)
let fstL f = lens fst (fun x (_, y) -> (x, y)) f
let sndL f = lens snd (fun y (x, _) -> (x, y)) f
// ----------------------------------------------------------------------------
// The code above taken from: http://www.fssnip.net/7Pk
// by Vesa+Karvonen - http://www.fssnip.net/authors/Vesa+Karvonen
// ----------------------------------------------------------------------------
let overAll l f = List.map (over l f)
open Lens
type Person<'T> = { Id : int; Value : 'T }
module Person =
let idS i p = { p with Id = i }
let valueS v { Id = i } = { Id = i; Value = v }
let idL f = lens (fun {Id = i } -> i) idS f
let valueL f = lens (fun {Value = v } -> v) valueS f
type Family<'T> = { Id : int; Members : Person<'T> list }
module Family =
let idS i f = { f with Id = i }
let membersS m { Id = i } = { Id = i; Members = m }
let idL f = lens (fun {Id = i } -> i) idS f
let membersL f = lens (fun {Members = m } -> m) membersS f
[<EntryPoint>]
let main argv =
let input =
{
Id = 1
Members = [{ Id = 10; Value = 123}; { Id = 11; Value = 456}]
}
printfn "%A" input
let output =
input
|> over Family.membersL (overAll Person.valueL ((+) 1 >> string))
printfn "%A" output
0
we had to implement the insert function that can insert a cell into a sorted linked list. My implementation idea was to have two rlists, called previous and current, that will be used to iterate through the list. At the beginning of the function call, the previous rlist will contain a random integer, and its next field is pointing to the current cell which is the head of the linked_list. I think this is problematic. I finished implementing my idea. I think the method will add the correct integer at the right place in the linked list. However, if the inserted element is at the beginning of the list, then the list is still the old list when using displaying on to the screen, but the old list does indeed have a cell pointing to it, and that cell has the inserted integer. So I'm not sure how to deal with that.
I tested my method, and it doesn't work as I described.
Here is what I did: I inserted -9 to the end of c3. c3 does indeed get -9 at the end of the list. And then I added 4 inside c5. But then c5 now becomes [5;4;-9]. So it is wrong, it should have [5;4;3;2;1;-9] instead. So I don't know what is wrong.
I looked up online on how to implement the method so that they can give me some inspirations or hint, but the solutions they provided are usually in Java or other programming languages.
type cell = { data : int; next : rlist}
and rlist = cell option ref
let c1 = {data = 1; next = ref None}
let c2 = {data = 2; next = ref (Some c1)}
let c3 = {data = 3; next = ref (Some c2)}
let c5 = {data = 5; next = ref (Some c3)}
let rec displayList (c : rlist) =
match !c with
| None -> []
| Some { data = d; next = l } -> d :: (displayList l)
let cell2rlist (c : cell) :rlist = ref (Some c)
let bigger((x:int), (y:int)) = (x > y)
let insert (comp : (int * int) -> bool) (item : int) (listt :rlist)=
let itemm = {data=item ; next = ref None} in
let rec helper (prev : rlist) (item : cell) (current: rlist) funcc =
match !current with
|None -> (match !prev with
|Some w -> w.next := (Some itemm))
|Some q -> if comp (item.data, q.data) then (itemm.next := (Some q) ; match !prev with
|Some w -> w.next := (Some itemm))
else prev := !current; current:= !(q.next); (helper prev item current funcc)
in let previous = ref (Some {data=0; next = listt}) in
helper previous itemm listt comp
Here are examples of the right return values for the code in action:
let l5 = cell2rlist c5;;
val l5 : rlist = ....
(* Messy display deleted. *)
displayList l5;;
- : int list = [5; 3; 2; 1]
displayList l5;;
- : int list = [5; 3; 2; 1]
insert bigger 4 l5;;
- : unit = ()
displayList l5;;
- : int list = [5; 4; 3; 2; 1]
insert bigger 9 l5;;
- : unit = ()
displayList l5;;
- : int list = [9; 5; 4; 3; 2; 1]
insert bigger 0 l5;;
- : unit = ()
displayList l5;;
- : int list = [9; 5; 4; 3; 2; 1; 0]
But when I ran my codes, here is what I get:
insert bigger 10 (ref(Some c5)) ;;
- : unit = ()
c5 ;;
- : cell =
{data = 5;
next =
{contents =
Some
{data = 3;
next =
{contents =
Some
{data = 2;
next = {contents = Some {data = 1; next = {contents = None}}}}}}}}
As you can see, if I insert a number that is supposed to be inserted at the beginning of the list, I can't see it.
Here is another example,
insert bigger 4 (ref(Some c5)) ;;
- : unit = ()
c5 ;;
- : cell =
{data = 5;
next =
{contents =
Some
{data = 4;
next = {contents = Some {data = 1; next = {contents = None}}}}}}
So as you see the code doesn't work at all as the updated list should have values [5;4;3;2;1] but it has [5;4;1] instead.
Here is another example:
insert bigger (-9) (ref(Some c3)) ;;
- : unit = ()
c3 ;;
- : cell =
{data = 3;
next =
{contents =
Some
{data = 2;
next =
{contents =
Some
{data = 1;
next = {contents = Some {data = -9; next = {contents = None}}}}}}}}
So it seems that the method does insert the element correctly into the list, but the lists that the inserted cell suppose to point to seem to be wrong.
For reference, here is a session showing a failure of your code:
# let (l: rlist) = ref None;;
val l : rlist = {contents = None}
# insert bigger 1 l;;
- : unit = ()
# l;;
- : rlist = {contents = Some {data = 1; next = {contents = None}}}
# insert bigger 0 l;;
- : unit = ()
# l;;
- : rlist = {contents = None}
For what it's worth, it would also be good if your code was indented properly.
At any rate, what I see when I look at your code for a short time is this fragment:
current:= !(q.next);
helper prev item current funcc
It looks to me like you're imagining that the first line here will advance some local variable to point to the next element of the list. But what it actually is doing is modifying the list.
You might want something more like this:
helper prev item q.next funcc
There are other problems in your code as well. It seems odd, for example, that the then part is parenthesized but the else part isn't parenthesized.
Could you guys explain how to use new groupBy in akka-streams ? Documentation seems to be quite useless. groupBy used to return (T, Source) but not anymore. Here is my example (I mimicked one from docs):
Source(List(
1 -> "1a", 1 -> "1b", 1 -> "1c",
2 -> "2a", 2 -> "2b",
3 -> "3a", 3 -> "3b", 3 -> "3c",
4 -> "4a",
5 -> "5a", 5 -> "5b", 5 -> "5c",
6 -> "6a", 6 -> "6b",
7 -> "7a",
8 -> "8a", 8 -> "8b",
9 -> "9a", 9 -> "9b",
))
.groupBy(3, _._1)
.map { case (aid, raw) =>
aid -> List(raw)
}
.reduce[(Int, List[String])] { case (l: (Int, List[String]), r: (Int, List[String])) =>
(l._1, l._2 ::: r._2)
}
.mergeSubstreams
.runForeach { case (aid: Int, items: List[String]) =>
println(s"$aid - ${items.length}")
}
This simply hangs. Perhaps it hangs because number of substreams is lower than number of unique keys. But what should I do if I have infinite stream ? I'd like to group until key changes.
In my real stream data is always sorted by value I'm grouping by. Perhaps I don't need groupBy at all ?
A year later, Akka Stream Contrib has a AccumulateWhileUnchanged class that does this:
libraryDependencies += "com.typesafe.akka" %% "akka-stream-contrib" % "0.9"
and:
import akka.stream.contrib.AccumulateWhileUnchanged
source.via(new AccumulateWhileUnchanged(_._1))
You could also achieve it using statefulMapConcat which will be a bit less expensive given that it does not do any sub-materialisations (but you have to live with the shame of using vars):
source.statefulMapConcat { () =>
var prevKey: Option[Int] = None
var acc: List[String] = Nil
{ case (newKey, str) =>
prevKey match {
case Some(`newKey`) | None =>
prevKey = Some(newKey)
acc = str :: acc
Nil
case Some(oldKey) =>
val accForOldKey = acc.reverse
prevKey = Some(newKey)
acc = str :: Nil
(oldKey -> accForOldKey) :: Nil
}
}
}.runForeach(println)
If your stream data is always sorted, you can leverage it for grouping this way:
val source = Source(List(
1 -> "1a", 1 -> "1b", 1 -> "1c",
2 -> "2a", 2 -> "2b",
3 -> "3a", 3 -> "3b", 3 -> "3c",
4 -> "4a",
5 -> "5a", 5 -> "5b", 5 -> "5c",
6 -> "6a", 6 -> "6b",
7 -> "7a",
8 -> "8a", 8 -> "8b",
9 -> "9a", 9 -> "9b",
))
source
// group elements by pairs
// the last one will be not a pair, but a single element
.sliding(2,1)
// when both keys in a pair are different, we split the group into a subflow
.splitAfter(pair => (pair.headOption, pair.lastOption) match {
case (Some((key1, _)), Some((key2, _))) => key1 != key2
})
// then we cut only the first element of the pair
// to reconstruct the original stream, but grouped by sorted key
.mapConcat(_.headOption.toList)
// then we fold the substream into a single element
.fold(0 -> List.empty[String]) {
case ((_, values), (key, value)) => key -> (value +: values)
}
// merge it back and dump the results
.mergeSubstreams
.runWith(Sink.foreach(println))
At the end you'll get these results:
(1,List(1c, 1b, 1a))
(2,List(2b, 2a))
(3,List(3c, 3b, 3a))
(4,List(4a))
(5,List(5c, 5b, 5a))
(6,List(6b, 6a))
(7,List(7a))
(8,List(8b, 8a))
(9,List(9a))
But compared to groupBy, you're not limited by the number of distinct keys.
I ended up implementing custom stage
class GroupAfterKeyChangeStage[K, T](keyForItem: T ⇒ K, maxBufferSize: Int) extends GraphStage[FlowShape[T, List[T]]] {
private val in = Inlet[T]("GroupAfterKeyChangeStage.in")
private val out = Outlet[List[T]]("GroupAfterKeyChangeStage.out")
override val shape: FlowShape[T, List[T]] =
FlowShape(in, out)
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler {
private val buffer = new ListBuffer[T]
private var currentKey: Option[K] = None
// InHandler
override def onPush(): Unit = {
val nextItem = grab(in)
val nextItemKey = keyForItem(nextItem)
if (currentKey.forall(_ == nextItemKey)) {
if (currentKey.isEmpty)
currentKey = Some(nextItemKey)
if (buffer.size == maxBufferSize)
failStage(new RuntimeException(s"Maximum buffer size is exceeded on key $nextItemKey"))
else {
buffer += nextItem
pull(in)
}
} else {
val result = buffer.result()
buffer.clear()
buffer += nextItem
currentKey = Some(nextItemKey)
push(out, result)
}
}
// OutHandler
override def onPull(): Unit = {
if (isClosed(in))
failStage(new RuntimeException("Upstream finished but there was a truncated final frame in the buffer"))
else
pull(in)
}
// InHandler
override def onUpstreamFinish(): Unit = {
val result = buffer.result()
if (result.nonEmpty) {
emit(out, result)
completeStage()
} else
completeStage()
// else swallow the termination and wait for pull
}
override def postStop(): Unit = {
buffer.clear()
}
setHandlers(in, out, this)
}
}
If you don't want to copy-paste it I've added it to helper library that I maintain. In order to use you need to add
Resolver.bintrayRepo("cppexpert", "maven")
to your resolvers. Add add foolowingto your dependencies
"com.walkmind" %% "scala-tricks" % "2.15"
It's implemented in com.walkmind.akkastream.FlowExt as flow
def groupSortedByKey[K, T](keyForItem: T ⇒ K, maxBufferSize: Int): Flow[T, List[T], NotUsed]
For my example it would be
source
.via(FlowExt.groupSortedByKey(_._1, 128))
So im in the early stages of learning how to use functional programming and I ran into this problem when I tried to compare a string with a string in a list, so that I could get the matching patterns.
Here is my code:
F# Code
type name = string;;
type number = string;;
type sex = string;;
type year = int;;
type interest = string list;;
type criteria = (sex * year * interest) list;;
type Register = (name * number * criteria) list;;
let reg = [("Lars","28551086",("male",1992,["soccer";"golf"])); ("Hanne","28598653",("female",1989,["cooking";"jewelry"]));
("Viktor","26587297",("male",1973,["clothes";"soccer"])); ("Henrik","22157864",("male",1985,["internet";"facebook"]));
("Lotte","23589462",("female",1997,["bombing";"internet"])); ("Susanne","25896742",("female",1923,["soccer";"cooking"]));
("Marie","22658943",("female",1975,["clothes";"jewelry"])) ];;
let rec findYear n = function
| [] -> failwith("No person with that year is registrered")
| (name,_,(_,n',_)) when n = n' -> name
| (name,_,(_,n',_))::tail when n <> n' -> findYear(tail);;
What im trying to do, is to retrieve all the people in the reg that has the same name as the one im searching for.
So a F# Interactive call could be:
findYear 1992;;
And then it should give me the details of the persons with that year. Im not sure how to search through my reg
I think you just forgot the n (and the tail of a list) here:
let rec findYear n = function
| [] -> failwith("No person with that year is registrered")
| (name,_,(_,n',_)) when n = n' -> name // forgot tail
| (name,_,(_,n',_))::tail when n <> n' -> findYear(tail) // forgot n here
(should have gotten an error
try this:
let rec findYear n = function
| [] -> failwith("No person with that year is registrered")
| ((name,_,(_,n',_))::_) when n = n' -> name
| ((_,_,(_,n',_))::tail) when n <> n' -> findYear n tail
making this a bit better
you don't need to check again
you don't need to recheck the year if the second pattern did not match:
let rec findYear n = function
| [] -> failwith("No person with that year is registrered")
| ((name,_,(_,n',_))::_) when n = n' -> name
| (_::tail) -> findYear n tail
option is better than an exception
The way you handle the case where you don't find a person with this year tells us that your function is "partial" (does not return for every input) - so just make it total again by using option:
let rec findYear n = function
| [] -> None
| ((name,_,(_,n',_))::_) when n = n' -> Some name
| (_::tail) -> findYear n tail
This will not throw and tell the user: "hey I might fail so better handle this!"
use records / ADTs
While your tuples are fine they are not really readable (hard to check if your pattern is ok for example) - why not use records and algebraic-data-types:
type Name = string
type Number = string
type Gender = Male | Female // add more if you need
type Year = int
type Interests = string list
type Criteria = { gender : Gender; year : Year; interests : Interests }
type Register = { name : Name; number : Number; criteria : Criteria }
let reg =
[ { name = "Lars"
; number = "28551086"
; criteria = { gender = Male; year = 1992; interests = ["soccer";"golf"] }
}
// ...
]
and use this:
let rec findYear n =
function
| [] -> None
| (reg::_) when reg.criteria.year = n'
-> Some reg
| (_::regs)
-> findYear n regs
use the List module
What you do here is a very common pattern and it's already implemented (List.tryFind) - so why not use it?
let findYear n =
let hasYear (reg : Register) = reg.criteria.year = n
List.tryFind hasYear
of course you can add the missing parameter if you don't really understand partial application yet:
let findYear n regs =
let hasYear (reg : Register) = reg.criteria.year = n
List.tryFind hasYear regs
finally let's give this a better name
this is of course just me not liking findYear if you really find a registration
// rest is the same
type Registration = { name : Name; number : Number; criteria : Criteria }
let firstRegistrationWithYear year =
let hasYear (reg : Register) = reg.criteria.year = year
List.tryFind hasYear
finding all registrations for one year
let filterRegistrationWithYear year =
let hasYear (reg : Register) = reg.criteria.year = year
List.filter hasYear
or if you want a (tail-recursive) implementation using continuation-passing style (the other answer has the accumulator aproach):
let filterYear n regs =
let rec filter regs cont =
match regs with
| [] -> cont []
| (reg::regs) when reg.criteria.year = n'
-> filter regs (fun res -> reg::res |> cont)
| (_::regs)
-> filter regs cont
filter regs id
remark:
I would not advise implementing this kind of stuff yourself - it's better to use the provided stuff from List (it's for example more performant as this, because I tried to show you how to do it CPS-style)
If you want to use recursion, you can add additional parameter (accumulator), to collect results:
let rec findYear n acc = function
| [] -> acc
| ((name,_,(_,n',_)) as h)::tail when n = n' -> findYear n (h::acc) tail
| h::tail -> findYear n acc tail
And call it this way:
findYear 1973 [] reg
Or you could use the 'filter' function from the List library functions:
let findYear' n lst =
lst |> List.filter (fun (name,_,(_,n',_)) -> n = n')
And call it this way:
findYear' 1973 reg
I need parse many-many relation.
I have list like:
[
{item1, [rel1, rel2, rel3]},
{item2, [rel2, rel5]},
{item3, [rel1, rel4]},
...
]
I need to build new list like:
[
{rel1, [item1, item3]},
{rel2, [item1, item2]},
...
]
How can I do it efficiently?
Most efficient way using dict:
F = fun({Item,Rels}, Dict) ->
H = fun(L) -> [Item|L] end,
G = fun(Rel, D) -> dict:update(Rel, H, [Item], D) end,
lists:foldl(G, Dict, Rels)
end,
dict:to_list(lists:foldl(F, dict:new(), Input)).
Using ets can be faster for really big data due less GC pressure:
Tab = ets:new(ok, [private]),
[ ets:insert(Tab,
{Rel, case ets:lookup(Tab, Rel) of
[] -> [Item];
[{_, L}] -> [Item|L]
end})
|| {Item, Rels} <- Input, Rel <- Rels ],
Result = ets:tab2list(Tab),
ets:delete(Tab),
Result.
Edit:
Since R17 there are maps and since R18 they should be efficient even for big amount of keys so now there is more efficient version using maps:
F = fun({Item, Rels}, Map) ->
G = fun(Rel, M) -> maps:put(Rel, [Item|maps:get(Rel, M, [])], M) end,
lists:foldl(G, Map, Rels)
end,
maps:to_list(lists:foldl(F, #{}, L)).
D = dict:from_list(INPUT),
F = fun(K,V,ACC) ->
dict:update(V, fun(X) -> [K|X] end, [X], ACC)
end
D2 = dict:fold(F, dict:new(), D),
OUTPUT = dict:to_list(D2).
convert_relation(Relations) ->
Dict =
lists:foldl(fun({Item, RelList}, Dict1) ->
lists:foldl(fun(Rel, Dict2) ->
dict:append(Rel, Item, Dict2)
end, Dict1, RelList)
end, dict:new(), Relations),
dict:to_list(Dict).