RSSAmplifier

Blog

Alexis King’s Blog

lexi-lambda.github.ioRSS feed ↗32 posts

Latest posts

A break from programming languages

This is a blog post I have been considering writing for a long time. People who have closely followed my work for the past few years have probably noticed that my output has gradually slowed. My last post on this blog was published over four years ago. The last talk I presented was almost two years ago, on work that I had recently finished but had started several years prior. My enthusiasm for my…

An introduction to typeclass metaprogramming

Typeclass metaprogramming is a powerful technique available to Haskell programmers to automatically generate term-level code from static type information. It has been used to great effect in several popular Haskell libraries (such as the servant ecosystem), and it is the core mechanism used to implement generic programming via GHC generics . Despite this, remarkably little material exists that…

Names are not type safety

Haskell programmers spend a lot of time talking about type safety . The Haskell school of program construction advocates “capturing invariants in the type system” and “making illegal states unrepresentable,” both of which sound like compelling goals, but are rather vague on the techniques used to achieve them. Almost exactly one year ago, I published Parse, Don’t Validate as an initial stab…

Types as axioms, or: playing god with static types

Just what exactly is a type? A common perspective is that types are restrictions . Static types restrict the set of values a variable may contain, capturing some subset of the space of “all possible values.” Under this worldview, a typechecker is sort of like an oracle, predicting which values will end up where when the program runs and making sure they satisfy the constraints the programmer wrote…

No, dynamic type systems are not inherently more open

Internet debates about typing disciplines continue to be plagued by a pervasive myth that dynamic type systems are inherently better at modeling “open world” domains. The argument usually goes like this: the goal of static typing is to pin everything down as much as possible, but in the real world, that just isn’t practical. Real systems should be loosely coupled and worry about data…

Parse, don’t validate

Historically, I’ve struggled to find a concise, simple way to explain what it means to practice type-driven design. Too often, when someone asks me “How did you come up with this approach?” I find I can’t give them a satisfying answer. I know it didn’t just come to me in a vision—I have an iterative design process that doesn’t require plucking the “right” approach out of thin air—yet I haven’t…

Empathy and subjective experience in programming languages

A stereotype about programmers is that they like to think in black and white. Programmers like things to be good or bad, moral or immoral, responsible or irresponsible. Perhaps there is something romantic in the idea that programmers like to be as binary as the computers they program. Reductionist? Almost certainly, but hey, laugh at yourself a bit: we probably deserve to be made fun of from time…

Demystifying MonadBaseControl

MonadBaseControl from the monad-control package is a confusing typeclass, and its methods have complicated types. For many people, it’s nothing more than scary, impossible-to-understand magic that is, for some reason, needed when lifting certain kinds of operations. Few resources exist that adequately explain how, why, and when it works, which sadly seems to have resulted in some FUD about its…

Defeating Racket’s separate compilation guarantee

Being a self-described programming-language programming language is an ambitious goal. To preserve predictability while permitting linguistic extension, Racket comes equipped with a module system carefully designed to accommodate composable and compilable macros . One of the module system’s foundational properties is its separate compilation guarantee , which imposes strong, unbreakable limits on…

Macroexpand anywhere with local-apply-transformer!

Racket programmers are accustomed to the language’s incredible capacity for extension and customization. Writing useful macros that do complicated things is easy, and it’s simple to add new syntactic forms to meet domain-specific needs. However, it doesn’t take long before many budding macrologists bump into the realization that only certain positions in Racket code are subject to macroexpansion.…

Custom core forms in Racket, part II: generalizing to arbitrary expressions and internal definitions

In my previous blog post , I covered the process involved in creating a small language with a custom set of core forms. Specifically, it discussed what was necessary to create Hackett’s type language, which involved expanding to custom expressions. While somewhat involved, Hackett’s type language was actually a relatively simple example to use, since it only made use of a subset of the linguistic…

Reimplementing Hackett’s type language: expanding to custom core forms in Racket

In the past couple of weeks, I completely rewrote the implementation of Hackett’s type language to improve the integration between the type representation and Racket’s macro system. The new type language effectively implements a way to reuse as much of the Racket macroexpanding infrastructure as possible while expanding a completely custom language, which uses a custom set of core forms. The…

An opinionated guide to Haskell in 2018

For me, this month marks the end of an era in my life: as of February 2018, I am no longer employed writing Haskell. It’s been a fascinating two years, and while I am excitedly looking forward to what I’ll be doing next, it’s likely I will continue to write Haskell in my spare time. I’ll probably even write it again professionally in the future. In the meantime, in the interest of both sharing…

A space of their own: adding a type namespace to Hackett

As previously discussed on this blog, my programming language, Hackett , is a fusion of two languages, Haskell and Racket. What happens when two distinctly different programming languages collide? Hackett recently faced that very problem when it came to the question of namespacing: Haskell has two namespaces, one for values and another for types, but Racket is a staunch Lisp-1 with a single…

Hackett progress report: documentation, quality of life, and snake

Three months ago, I wrote a blog post describing my new, prototype implementation of my programming language, Hackett . At the time, some things looked promising—the language already included algebraic datatypes, typeclasses, laziness, and even a mini, proof of concept web server. It was, however, clearly still rather rough around the edges—error messages were poor, features were sometimes…

User-programmable infix operators in Racket

Lisps are not known for infix operators, quite the opposite; infix operators generally involve more syntax and parsing than Lispers are keen to support. However, in Hackett , all functions are curried, and variable-arity functions do not exist. Infix operators are almost necessary for that to be palatable, and though there are other reasons to want them, it may not be obvious how to support them…

Unit testing effectful Haskell with monad-mock

Nearly eight months ago, I wrote a blog post about unit testing effectful Haskell code using a library called test-fixture. That library has served us well, but it wasn’t as easy to use as I would have liked, and it worked better with certain patterns than others. Since then, I’ve learned more about Haskell and more about testing, and I’m pleased to announce that I am releasing an entirely new…

Realizing Hackett, a metaprogrammable Haskell

Almost five months ago, I wrote a blog post about my new programming language, Hackett , a fanciful sketch of a programming language from a far-off land with Haskell’s type system and Racket’s macros. At that point in time, I had a little prototype that barely worked, that I barely understood, and was a little bit of a technical dead-end. People saw the post, they got excited, but development sort…

Lifts for free: making mtl typeclasses derivable

Perhaps the most important abstraction a Haskell programmer must understand to effectively write modern Haskell code, beyond the level of the monad, is the monad transformer , a way to compose monads together in a limited fashion. One frustrating downside to monad transformers is a proliferation of lift s, which explicitly indicate which monad in a transformer “stack” a particular computation…

Rascal is now Hackett, plus some answers to questions

Since I published my blog post introducing Rascal , I’ve gotten some amazing feedback, more than I had ever anticipated! One of the things that was pointed out, though, is that Rascal is a language that already exists . Given that the name “Rascal” came from a mixture of “Racket” and “Haskell”, I always had an alternative named planned, and that’s “Hackett”. So, to avoid confusion as much as…

Rascal: a Haskell with more parentheses

Note : since the writing of this blog post, Rascal has been renamed to Hackett. You can read about why in the followup blog post . “Hey! You got your Haskell in my Racket!” “No, you got your Racket in my Haskell!” Welcome to the Rascal programming language. Why Rascal? Why yet another programming language? Anyone who knows me knows that I already have two programming languages that I really like:…

Using types to unit-test in Haskell

Object-oriented programming languages make unit testing easy by providing obvious boundaries between units of code in the form of classes and interfaces. These boundaries make it easy to stub out parts of a system to test functionality in isolation, which makes it possible to write fast, deterministic test suites that are robust in the face of change. When writing Haskell, it can be unclear how to…

Understanding the npm dependency model

Currently, npm is the package manager for the frontend world. Sure, there are alternatives, but for the time being, npm seems to have won. Even tools like Bower are being pushed to the wayside in favor of the One True Package Manager, but what’s most interesting to me is npm’s relatively novel approach to dependency management. Unfortunately, in my experience, it is actually not particularly well…

Climbing the infinite ladder of abstraction

I started programming in elementary school. When I was young, I was fascinated by the idea of automation. I loathed doing the same repetitive task over and over again, and I always yearned for a way to solve the general problem . When I learned about programming, I was immediately hooked: it was so easy to turn repetitive tasks into automated pipelines that would free me from ever having to do the…

Four months with Haskell

At the end of January of this year, I switched to a new job, almost exclusively because I was enticed by the idea of being able to write Haskell. The concept of using such an interesting programming language every day instead of what I’d been doing before (mostly Rails and JavaScript) was very exciting, and I’m pleased to say that the switch seems to have been well worth it. Haskell was a language…

Simple, safe multimethods in Racket

Racket ships with racket/generic , a system for defining generic methods , functions that work differently depending on what sort of value they are supplied. I have made heavy use of this feature in my collections library, and it has worked well for my needs, but that system does have a bit of a limitation: it only supports single dispatch . Method implementations may only be chosen based on a…

ADTs in Typed Racket with macros

Macros are one of Racket's flagship features, and its macro system really is state of the art. Of course, it can sometimes be difficult to demonstrate why macros are so highly esteemed, in part because it can be hard to find self-contained examples of using macros in practice. Of course, one thing that macros are perfect for is filling a "hole" in the language by introducing a feature a language…

Functionally updating record types in Elm

Elm is a wonderful language for building web apps, and I love so much of its approach to language design. Elm does so many things right straight out of the box, and that's a real breath of fresh air in the intersection of functional programming and web development. Still, it gets one thing wrong, and unfortunately, that one thing is incredibly important. Elm took the "functions" out of "functional…

Canonical factories for testing with factory_girl_api

Modern web applications are often built as single-page apps , which are great for keeping concerns separated, but problematic when tested. Logic needs to be duplicated in front- and back-end test suites, and if the two apps diverge, the tests won't catch the failure. I haven't found a very good solution to this problem aside from brittle, end-to-end integration tests. To attempt to address a…

Managing application configuration with Envy

Application configuration can be a pain. Modern web apps don't live on dedicated boxes, they run on VPSes somewhere in the amorphous "cloud", and keeping configuration out of your application's repository can seem like more trouble than it's worth. Fortunately, The Twelve-Factor App provides a set of standards for keeping web apps sane, and one of those guidelines advises keeping configuration in…

Deploying Racket applications on Heroku

Heroku is a "platform as a service" that provides an incredibly simple way to deploy simple internet applications, and I take liberal advantage of its free tier for testing out simple applications. It has support for a variety of languages built-in, but Racket is not currently among them. Fortunately, Heroku provides an interface for adding custom build processes for arbitrary types of…

Automatically deploying a Frog-powered blog to GitHub pages

So, I have a blog now. It's a simple static blog, but what's unique about it is that it's powered by Racket; specifically, it uses Greg Hendershott 's fantastic Frog tool. I've taken this and moulded it to my tastes to build my blog, including configuring automatic deployment via Travis CI , so my blog is always up-to-date. Setting up Frog I should note that Frog itself was wonderfully easy to…