Calculate click-through rate (CTR) with Stream Processing

For calculating CTR (Click Through Rate) we can create two activity stream:

  1. Search Events
  2. Click Events

create table of two corresponding search events and click events with Stream-stream join using one of Stream Processing engine, so we can count number of clicks and number of total search and calculate CTR.

Knapsack

This video is a good start to learn how to solve 0/1 Knapsack problem with Dynamic Programming. If you want to solve dynamic programmings in functional paradigm, see these series of articles.

Conversion Between DTO and Entity Classes in Scala

When you practicing DDD (Domain-Driven-Design), you need to create different bounded countexts, for example when you receive DTO object PersonDTO, It should be mapped to PersonEntity. This conversion, have lots of repetitive works to copy fields of one object to another.

In scala there is type-safa data transoformer chimney which can do it for you with macros and providing simple dsl for it.

Scala-Automapper is another library which is similar to chimney but when you have some difference in fields type, you can’t do it, easily like chimney

Scala Intramap

Intramap have following definition:

def imap[A, B](fa: F[A])(f: A => B)(g: B => A): F[B]

So when you have Funtor[A] and you want to create new Functor[B] which is invariant with Functor[A] you can use imap method.

In following example, You I’ve wrote Codec for Person type, by using String Codec.

trait Codec[A] {
  self =>
  def encode(value: A): String

  def decode(value: String): A

  def imap[B](dec: A => B, enc: B => A): Codec[B] = new Codec[B] {
    override def encode(value: B): String =
      self.encode(enc(value))

    override def decode(value: String): B =
      dec(self.decode(value))
  }
}

def encode[A](value: A)(implicit c: Codec[A]): String = c.encode(value)

def decode[A](value: String)(implicit c: Codec[A]): A = c.decode(value)


object CodecImplicits {


  implicit val stringCodec: Codec[String] = new Codec[String] {
    override def encode(value: String): String = value

    override def decode(value: String): String = value
  }

  implicit val intCodec: Codec[Int] = stringCodec.imap(
    _.toInt, _.toString
  )
}

import CodecImplicits._

case class Person(name: String, age: Int)

implicit val personCodec: Codec[Person] = stringCodec.imap[Person](
  str => {
    val lines = str.split(',')
    Person(decode[String](lines(0)), decode[Int](lines(1)))
  },
  person => s"${person.name},${person.age}"
)

val ali: String = encode[Person](Person("Ali", 25))
val mohammad: Person = decode[Person]("Mohammad,23")

println(ali)
println(mohammad)

Result:

Ali,25
Person(Mohammad,23)

Scala Contramap

Contramap function have the following definition:

def contramap[A, B](fa: F[A])(f: B => A): F[B]

For example scala.math.Ordering have by function that is contramap, we can create Complicated orderings by use of Simple Orderings.

def by[T, S](f: T => S)(implicit ord: Ordering[S]): Ordering[T]

Create Ordering for type Money with by contramap

case class Money(amount: Int)

import scala.math.Ordered._

implicit val moneyOrdering: Ordering[Money] = Ordering.by(_.amount)

Money(300) < Money(200)