Skip to content

Instantly share code, notes, and snippets.

View afsalthaj's full-sized avatar

Afsal Thaj afsalthaj

View GitHub Profile
implicit val validateName: Validation[Name] =
_.successNel[ValidationError]
implicit val validateExchangeId: Validation[ExchangeId]=
_.successNel[ValidationError]
import shapeless.{HList, ::, HNil }
import scalaz.syntax.applicative._
import scalaz.syntax.either._
import scalaz.syntax.validation._
implicit val hnilEncode: Validation[HNil] =
Validation.createInstance( _.successNel[ValidationError]) //Yea, that's it
implicit def hlistEncoder[H, T <: HList] (
implicit
implicit def genericValidation[A, R](
implicit gen: Generic.Aux[A, R], env: Validation[R]
): Validation[A] =
new Validation[A] {
override def validate(b: A) =
env.validate(gen.to(b)).map(gen.from)
}
// Please note that Generic.Aux[A, R] === Generic[A] {type Repr = R}
// as we cannot do env: Validation[gen.Repr]
@ //This is ammonite configured for shapeless
@ implicitly[Validation[SuperExchange]].validate(SuperExchange(ExchangeId("id"), Name("name")))
res48: ValidationNel[ValidationError, SuperExchange] = Success(SuperExchange("id", "name"))
@ //This is ammonite configured for shapeless
@ object NewNumber extends Tagger[Int]
defined object NewNumber
@ type NewNumber = NewNumber.Type
defined type NewNumber
@ case class World(name: Name, exchangId: ExchangeId, newNumber: NewNumber)
defined class World
package com.telstra.dxhub.productmapper
import shapeless.{::, Generic, HList, HNil, Poly, Poly1}
import shapeless.PolyDefns.{Case, Case0}
import shapeless.ops.hlist.Mapper
trait ProductMapper[A, B, P] {
def apply(a: A): B
}
package com.thaj.functionalprogramming.exercises.part4
import scalaz.{ Scalaz, _ }
import Scalaz._
// Thanks to https://underscore.io/blog/posts/2017/03/29/free-inject.html
object CombineFreeInScalaz {
sealed trait Logging[A]
case class Info(s: String) extends Logging[Unit]
import java.time.Instant
import java.util.concurrent.atomic.{AtomicReference, AtomicReferenceArray}
import monix.eval.Task
import monix.execution.atomic.AtomicLong
import monix.reactive.{Consumer, Observable}
import monix.reactive.observables.ObservableLike.Transformer
import scala.annotation.tailrec
// The code base below shows how horrible it is to use AtomicReference
// (Yes, we are talking about concurrency) in the world of mutation.
// This should be one of your answer to why you hate mutation for the sake of performance - 
// The gist is a simple example to ABA problem.
// While the problem sounds ridiculously easy, the gist show how can it happen in a real world,
// and how on earth can it lead to program error.
@ val s = new AtomicLong(0)
s: AtomicLong = 0

A few random thoughts on FP

Parametricity for the win!

Type parameterisation is done for us to later discover, for instance, that we could test our CRUD service layer with all combinations of errors a database can produce as a single test case. How many applications do that?...

Laws!

Any implementations should go with property based tests/laws. Else it is fairly hard to convince even ourselves why not a Java/Python/any imperative alternate. Let's don't be biased for no reason.

It is easier to convince that concurrency management and related library development with Scala (well, FP) is better as we love compositions than call backs and waiting. But application level FP usage is justified, for instance, when you are able to say “Let me push to master, coz it will work for sure”. That confidence comes easily with type driven development and laws.