Skip to content

Instantly share code, notes, and snippets.

View debasishg's full-sized avatar
Working from home

Debasish Ghosh debasishg

Working from home
View GitHub Profile
debasishg /
Last active January 23, 2024 05:51
Rust Idiom (Trait Bounds)

Trait Bounds

Trait bounds in Rust are really powerful and also offers lots of idiomatic ways to constrain your model. Bounds are for enforcing constraints even in other languages like Scala, but Rust offers them at a different level.

Here's one example from the book Rust for Rustaceans (a great book BTW).

Suppose you want to construct a HashMap<K, V, S>, whose keys are some generic type T, value is a usize, you can write bounds like T: Hash + Eq, S: BuildHasher + Default.

pub fn doit<T>(value: T)
debasishg /
Last active November 16, 2023 14:07
OCaml domain modeling

Abstraction and Parametricity implementing domain models in OCaml

One of my favorite comments on abstraction and parametricity ..

Parametricity can be thought of as the dual to abstraction. Where abstraction hides details about an implementation from the outside world, parametricity hides details about the outside world from an implementation.

When using OCaml as the implementation language, you abstract using ADTs (Abstract Data Types) and make your abstraction parametric using functors. And bind all of the algebras together using Modules.


(* Modules - the signature of functions and types with no
implementation whatsoever. Pure interfaces. *)
module type OrderedType = sig
type t
val compare : t -> t -> int
(* Note we don't specify any representation for the implementation of a
[heap]. Just the facts that define a heap - an ordered element, an
abstract type and a bunch of functions *)
debasishg /
Created October 12, 2023 16:47 — forked from jonsterling/
existential quantifier in OCaml
(* an abstract signature for instantiations of the existential quantifier *)
module type EXISTS =
(* the predicate *)
type 'a phi
(* the existential type *)
type t
(* the introduction rule *)
debasishg /
Last active October 26, 2023 23:11
a brief intro to algebraic domain modeling

Algebraic Domain Modeling

When we talk about the algebra of an operation, we talk about the signature of the operation, and how, starting from the input, we can just "follow the types" to lead to the implementation of that operation.

Consider the following operation generateTrades as part of a domain service TradingService. The idea is to generate all trades that happened on the day (input to the operation) and executed by the user (input to the operation) in the back-office of a securities trading organization.

In the example below, note the following 2 principles that form the core of the algebraic modeling:

  1. The sequence of steps mentioned in the specification of the method as comments and correspond one-to-one to the types of the operations used in implementing generateTrades. I have annotated the steps in the implementation below.
  2. The implementation of generateTrades is completely decoupled from the implementation of the operations like queryExecutionsForDate, `getAccountNoF
debasishg /
Last active February 17, 2024 15:03
Papers related to cache oblivious data structures

Cache Oblivious and Cache Aware Data Structure and Algorithms

  1. Cache-Oblivious Algorithms and Data Structures - Erik Demaine (One of the earliest papers in cache oblivious data structures and algorithms that introduces the cache oblivious model in detail and examines static and dynamic cache oblivious data structures built between 2000-2003)

  2. Cache Oblivious B-Trees - Bender, Demaine, Farch-Colton (This paper presents two dynamic search trees attaining near-optimal performance on any hierarchical memory. One of the fundamental papers in the field where both search trees discussed match the optimal search bound of Θ(1+log (B+1)N) memory transfers)

  3. Cache Oblivious Search Trees via Binary Trees of Small Height - Brodal, Fagerberg, Jacob (The data structure discussed in this paper works on the version of [2] but avoids the use o

package cqrs
package eventstore
import zio.*
import zio.prelude.*
import zio.prelude.fx.*
object BaseSyntax:
type Program[S, R, E, A] = ZPure[Nothing, S, S, R, E, A]

Thinking differently between frameworks with concrete abstractions (ZIO in Scala) and those with algebras and typeclasses (Haskell / cats & cats-effects in Scala) :-

Using Haskell or Scala cats / cats-effect, which offers libraries based on algebras and typeclasses, we think in terms of the algebra and the appropriate typeclass to model the effect. It's always algebra first - in the following example, we fetch an entity to work with in a domain model. We try fetching from the cache first and if we get a cache miss we reach out for a database based query. With Haskell or cats in Scala, the mantra is using the algebra of an Alternative typeclass.

getAccount = runMaybeT $
      MaybeT (AC.fetchCachedAccount ano) 
  <|> MaybeT (AR.queryAccount ano)
debasishg / ZKleisli.scala
Created September 28, 2022 15:44
ZIO Kleisli
package zio
case class ZKleisli[-R, +E, -A, +B](
run: A => ZIO[R, E, B]
) { self =>
// compose with a ZIO not lifted into a Kleisli
def mapZIO[R1 <: R, E1 >: E, A1 <: A, C1](bc: B => ZIO[R1, E1, C1]): ZKleisli[R1, E1, A, C1] =
// Modify the output of the Kleisli function with `f`