Skip to content
View rafafrdz's full-sized avatar
Coding!
Coding!

Highlights

  • Pro

Organizations

@eff3ct0

Block or report rafafrdz

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Maximum 250 characters. Please don't include any personal information such as legal names or email addresses. Markdown supported. This note will be visible to only you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
rafafrdz/README.md

Header

Rafael Fernández

Functional programmer focused on type-driven design, lawful abstractions, and effectful systems.

My work sits at the intersection of Scala, category theory, and systems programming with Rust. I design software where types carry meaning, effects are explicit, and composition is the primary tool.

- If an invariant is not encoded in the type system, it is merely a convention.

To code or not to code, that is the question png - My Writing & Thought Workflow

I write on my blog about functional programming, Scala, and software architecture, focusing on practical FP rather than academic exercises.

Coffee time... Let's talk!png - Freelance

Available for freelance work and technical consulting. See my website, CV or my LinkedIn. If your system is growing faster than your confidence in it, we should talk.

Design Principles (Non-Negotiable)

  • Typeclasses over inheritance
  • Algebras over implementations
  • Effects are values, not side effects
  • Explicit dependencies via parametric polymorphism
  • Laws first, optimizations second (but never ignored)
  • Make illegal states unrepresentable

About me

I don’t see Functional Programming as a style or a set of tools, but as a discipline for reasoning about software.

My goal is not to write “clever” code, but to build systems that remain understandable, correct, and evolvable under pressure.

1. Types are not documentation

Types are executable constraints. If an invariant matters, it belongs in the type system. If a function accepts more states than it can handle, it is lying.

2. Effects must be explicit

Effects are not something that happens — they are something that is described. An effectful program is a value. Interpretation is a separate concern. Hidden effects are technical debt.

3. Abstractions must be lawful

An abstraction without laws is just an interface. Laws are what allow refactoring without fear and composition without surprise. If an abstraction cannot be reasoned about algebraically, it is probably the wrong abstraction.

4. Composition is the only scaling strategy

Large systems are not built by adding features, but by composing smaller, well-behaved parts.

Composition works when:

  • Dependencies are explicit
  • Effects are controlled
  • Data flows are unidirectional

Inheritance does not scale. Composition does.

5. Make illegal states unrepresentable

Every runtime check is a failure to model the domain correctly. The earlier an invalid state is rejected, the cheaper it is. The best error is the one that cannot be expressed.

6. Performance is a feature, not an excuse

Abstractions are allowed. Accidental complexity is not. I care about performance, but never at the cost of correctness or clarity. Good FP and high performance are not opposites — they are often aligned.

7. Simplicity is not minimalism

Fewer concepts do not automatically mean simpler systems. True simplicity comes from clear boundaries, precise models, and predictable behavior. A small but leaky abstraction is worse than a larger but honest one.

Algebra First, Implementation Later

🧬 Scala — Tagless Final, Typeclasses, Laws

The following Scala snippet shows how these principles translate into a real design: algebras expressed as typeclasses, effect-polymorphic programs, and interpreter-free composition.

- No inheritance trees. No hidden effects. Only algebras, interpreters, and laws.

// Domain
final case class Timeline[A](at: Date, value: A)

// Algebra
trait PersonAlg[F[_]] {
  def about: F[Info]
  def experience: F[List[Timeline[Experience]]]
  def education: F[List[Timeline[Education]]]
  def skills: F[Stack]
}

// Program
trait CurriculumVitae[F[_]] {
  def about: F[Info]
  def experience(at: Date): F[List[Experience]]
  def education(at: Date): F[List[Education]]
  def skills: F[Stack]
}

// Interpreter-free construction
object CurriculumVitae {

  def apply[F[_]: MonadFilter](P: PersonAlg[F]): CurriculumVitae[F] =
    new CurriculumVitae[F] {

      def about: F[Info] =
        P.about

      def experience(at: Date): F[List[Experience]] =
        P.experience.map(_.mapFilter(collectUntil(at)))

      def education(at: Date): F[List[Education]] =
        P.education.map(_.mapFilter(collectUntil(at)))

      def skills: F[Stack] =
        P.skills
    }

  def collectUntil[A](at: Date): Timeline[A] => Option[A] = {
     case Timeline(date, value) if date <= at => Some(value)
     case _                                  => None
   }
}

🦀 Rust — Traits, Ownership, Zero-Cost Abstractions

This Rust example mirrors the same architectural ideas: traits as algebras, explicit effects via Result, and correctness enforced by the type system.

- Ownership enforces correctness. Traits define behavior. Abstractions compile away.

Show Scala example
use std::collections::HashMap;

// Domain
#[derive(Clone)]
pub struct Timeline<A> {
    pub at: Date,
    pub value: A,
}

// Algebra
pub trait PersonAlg {
    type Error;

    fn about(&self) -> Result<Info, Self::Error>;
    fn experience(&self) -> Result<Vec<Timeline<Experience>>, Self::Error>;
    fn education(&self) -> Result<Vec<Timeline<Education>>, Self::Error>;
    fn skills(&self) -> Result<Stack, Self::Error>;
}

// Program
pub struct CurriculumVitae<P> {
    person: P,
}

impl<P> CurriculumVitae<P>
where
    P: PersonAlg,
{
    pub fn new(person: P) -> Self {
        Self { person }
    }

    fn collect_until<A>(at: Date, xs: Vec<Timeline<A>>) -> Vec<A> {
        xs.into_iter()
            .filter(|t| t.at <= at)
            .map(|t| t.value)
            .collect()
    }

    pub fn experience(&self, at: Date) -> Result<Vec<Experience>, P::Error> {
        self.person.experience().map(|xs| Self::collect_until(at, xs))
    }

    pub fn education(&self, at: Date) -> Result<Vec<Education>, P::Error> {
        self.person.education().map(|xs| Self::collect_until(at, xs))
    }
}

Pinned Loading

  1. eff3ct0/criteria4s eff3ct0/criteria4s Public

    Criteria4s is a simple DSL to define criteria and predicate expressions for any data stores by using Scala type class mechanisms in a type-safe

    Scala 21 3

  2. eff3ct0/teckel eff3ct0/teckel Public

    Teckle framework for building Apache Spark ETL processes using YAML configuration files.

    Scala 10 2

  3. table-trace-rs table-trace-rs Public

    TableTrace is a lightweight HTTP API that extracts the table names involved in a given SQL query. It supports parsing queries and returning a JSON list of table names.

    Rust

  4. table-trace table-trace Public

    TableTrace is a lightweight HTTP API that extracts the table names involved in a given SQL query. It supports parsing queries and returning a JSON list of table names.

    Scala

  5. automated-gmail-app automated-gmail-app Public

    An asynchronous, lightweight and non-blocking app built on Scala

    Scala

  6. ethereum-control-flow-graph-bytecode ethereum-control-flow-graph-bytecode Public

    Ethereum bytecode analyzer with Control-Flow Graph method

    Scala 1