Learn Haskell Blog Generator

website·Indexed 30 days ago

https://jbl428.github.io

A comprehensive guide to learning Haskell by building a blog generator. The tutorial covers creating an HTML EDSL, parsing custom markup languages into Haskell data types, handling IO and error management with Either and ExceptT, and implementing a command-line interface using optparse-applicative. It also explores project specification with .cabal files, testing, and documentation using Haddock.

Tokens
91.6K
Snippets
465
Records
547
Agent score
75%

What's inside Learn Haskell Blog Generator

  1. Model failure with reasons using the Either type

    While Option represents the presence or absence of a value, Either<E, A> is used to represent a computation that can either fail with a specific error of type E (Left) or succeed with a value of type A (Right).
    interface Left<E> { readonly _tag: 'Left'; readonly left: E }
    interface Right<A> { readonly _tag: 'Right'; readonly right: A }
    type Either<E, A> = Left<E> | Right<A>
    
    const left = <E, A>(left: E): Either<E, A> => ({ _tag: 'Left', left })
    const right = <A, E>(right: A): Either<E, A> => ({ _tag: 'Right', right })
    
    const match = <E, R, A>(onLeft: (left: E) => R, onRight: (right: A) => R) => 
      (fa: Either<E, A>): R => {
        switch (fa._tag) {
          case 'Left': return onLeft(fa.left)
          case 'Right': return onRight(fa.right)
        }
      }
  2. Principles of testable code

    Testable code typically exhibits the following characteristics: modularity, single purpose, explicitness, low coupling, separation of pure and impure logic, and conciseness. Functional programming facilitates these goals, and the Effect-TS library (a TypeScript port of Scala's ZIO) is specifically designed to enable the creation of testable code.
  3. Understanding the limitation of Functors for multi-argument functions

    In functional programming, a Functor allows the composition of an effectful program f: (a: A) => F<B> with a pure unary function g: (b: B) => C using map(g). However, Functors are limited to unary functions. If a pure function g requires multiple parameters (e.g., two arguments), a standard Functor instance cannot transform g to operate on effectful values, necessitating the use of Applicative Functors.
    // Functor composition (Unary)
    // f: (a: A) => F<B>
    // g: (b: B) => C
    // Result: map(g) ∘ f
  4. Use LocalStack to simulate AWS services locally

    LocalStack is an AWS infrastructure simulator that allows developers to run and test AWS services in a local environment. Supported services include Lambda, S3, DynamoDB, Kinesis, SQS, SNS, and SES (Simple Email Service).
  5. Understand the two fundamental pillars of functional programming

    Functional programming is built upon two core foundational elements:

    1. Referential Transparency: The property where an expression can be replaced with its value without changing the program's behavior.
    2. Composition: Used as a general design pattern to combine simple functions to build more complex ones.
  6. Understand the core concepts of Functional Programming

    Functional Programming (FP) is a paradigm that utilizes pure functions and mathematical models to manage system complexity.

    Key concepts include:

    • Pure Functions: Procedures that always produce the same output for the same input and have no side effects.
    • Side Effects: Any operation a function performs other than returning a value, such as writing to a database or opening a file.
    • Goal: To tame system complexity using formal models, focusing on code properties and ease of refactoring. This enables developers to write composable code, handle side effects predictably, and create consistent, generic, and systematic APIs.
  7. Implement Hexagonal Architecture in Nest.js

    The project uses a Hexagonal Architecture (Ports and Adapters pattern) to decouple business logic from infrastructure. The directory structure is divided into three main layers:

    • Domain: Contains pure classes with core business logic and domain models.
    • Application: Contains business logic that utilizes domain models. It defines inbound port interfaces (for external use) and outbound port interfaces (used by services).
    • Adapter: Contains infrastructure-related logic (GraphQL, Notifications, DB). Adapters implement outbound ports and use inbound ports to handle API requests and responses.
    sample
    ├── SampleModule.ts
    ├── adapter
    │   ├── in
    │   │   └── gql
    │   │       ├── SampleMutationResolver.ts
    │   │       ├── SampleQueryResolver.ts
    │   │       └── SampleSubscriptionResolver.ts
    │   └── out
    │       └── persistence
    │           ├── SampleOrmMapper.ts
    │           └── SampleRepositoryAdapter.ts
    ├── application
    │   ├── port
    │   │   ├── in
    │   │   │   └── SampleCommandUseCase.ts
    │   │   └── out
    │   │       └── SampleRepositoryPort.ts
    │   └── service
    │       └── SampleCommandService.ts
    └── domain
        └── Sample.ts
  8. Understand Semigroups as a blueprint for combining values

    A semigroup is an algebraic structure (algebra) that serves as a blueprint for combining two or more values. In the context of functional programming and mathematics, an algebra is defined by a combination of one or more sets, one or more operations on those sets, and zero or more laws governing those operations. This can be viewed as a high-level abstraction of an interface where modifications to the state are only permitted through the operations defined by the algebra's own laws.
  9. Understand Algebraic Data Types (ADTs) in Functional Programming

    In computer programming, specifically within functional programming and type theory, Algebraic Data Types (ADTs) are a category of composite types. They are constructed by combining other types and are fundamentally divided into two categories: Product Types and Sum Types.
  10. Use Utterances for GitHub-based website comments

    Utterances is a service that allows you to implement a comment section on your website by leveraging GitHub Issues. Because it uses GitHub's infrastructure, users must have a GitHub account to post comments. For those requiring broader social login support (beyond GitHub), alternatives like Disqus are recommended.
  11. Model fixed sets of options using enum classes (Sum Types)

    When a domain concept consists of a fixed set of possible values (an 'OR' relationship), use an enum class. This is referred to as a sum type in functional programming. Using an enum instead of a String reduces complexity and prevents invalid values from being assigned to the property.
    enum class AgeRestriction(val description: String) {
      General("All ages admitted."),
      PG("Parental guidance suggested"),
      PG13("Parents urged to be cautious"),
      Restricted("Under 17 requires guardian"),
      NC17("No One 17 and Under Admitted")
    }