The ACME category on Hackage is for joke packages. The name “Acme” is a reference to the name of the company from which Wile E. Coyote obtains dangerous contraptions that always backfire.
A collection of articles highlighting Haskell libraries that generate art.
Most of the datatypes you’re used to follow a simple pattern: the data constructors’ type parameters match up with the kind of the type constructor. This series is about ways to deviate from the regular path and define slightly more exotic types. 1. By placing equality constraints (
~) on a data constructor, we can reduce the number of parameters it has relative to the kind of the type constructor; 2. Using the
forall keyword in a data constructor, we can increase the number of the type parameters it has relative to the kind of the type constructor. The first lessons will establish some foundations, and subsequent lessons will apply these concepts to practical demonstrations.
This lesson explains what it means for data constructors to have constraints, a special constraint called type equality, written as
(~), and why placing a type equality constraint on a constructor has interesting ramifications.
The ‘newtype’ keyword allows us to define a new type that has the same runtime representation as another type. This can become more cumbersome as the code grows more complicated or as we add more layers of newtypes. Fortunately, GHC gives us some tools that help us express trivial type conversions more easily. The ‘coerce’ function can convert between two types A and B as long as the constraint Coercible A B is satisfied.
If you replace an expression <expr> with $(lift <expr>), then that expression will be evaluated during compilation. If you have reason to be concerned that evaluation of <expr> may fail, this technique has the benefit of giving you a compilation failure instead of producing a program that fails by throwing an exception at runtime.
The concept of contravariance, contravariant functors, and the Contravariant typeclass defined in the ‘contravariance’ Haskell library.
Both Haskell98 and Haskell2010 allow datatypes to have contexts, that is, typeclass constraints on the type parameters. Currently this is still allowed only with the -XDatatypeContexts extension turned on, and this feature will be removed from the next Haskell language standard. This article looks at why this feature has been deprecated.
The compiler will issue a warning about an unused definition because it is likely a sign of a mistake. Using an underscore as the first character in a value-level identifier conventionally signifies that the value is unused, which suppresses this warning.
GHC Haskell has an overwhelming number of language extensions. Some are well documented, others are sparsely documented; some are common, others are exotic. It can be difficult terrain to navigate. Most programs can be written in vanilla Haskell with no extensions enabled. The extensions do not change the languages or its semantics. They are compiler extensions and change the way the compiler does its job, the way it reads the code. Hence, if you are using a compiler other than GHC (or are using a very old version of GHC), you may not have access to any of these extensions or only to some subset. Here we covers the extensions we think are most likely to be useful and helpful to the Haskell beginner or early intermediate as well as a few having to do with issues that crop up whether you’re ready for them or not. Each has a link to a longer article about it, describing it in more detail.
An organized listing of the functions we’ve singled out for praise.
This series covers the ‘Applicative’ typeclass and two of its close relatives, ‘Alternative’ and ‘Traversable’. After thoroughly treating several practical examples and some important applicative functors, we look at the laws of the class and property testing them with ‘hedgehog’.
This series gives a detailed explanation of the two most basic functor typeclasses, including examples of usage, and their laws. It also introduces using the ‘hedgehog’ library for property testing.
GHC is the Haskell compiler. In addition the compiler, GHC also includes a REPL called GHCi (“GHC interactive”), an executable called
runghc to run Haskell source files directly without a compilation step, and a great number of extensions to the Haskell language which can enable features beyond what is given in the Haskell language specification.
The Haskell REPL, GHCi, is a great interactive development tool with a lot of features. This series explains some aspects of GHCi that are not always obvious and brings some of those features to light.
Do-notation has historically been reserved for monadic contexts, most commonly used with IO. The ApplicativeDo extension allows you to use do-notation in an applicative context.
The BlockArguments extensions allows certain expressions – most notably do-blocks but also lambda expressions and case expressions – to be used as arguments to functions without use of parentheses or the dollar sign to signal the correct associativity.
Although it is technically possible to write your own instances of the Generic typeclass, in practice we nearly always let GHC derive it for us. For that, we must enable the DeriveGeneric language extension. Generic can be derived for all but the most exotic datatypes. The DeriveGeneric extension first appeared in GHC version 7.2.1.
The DeriveLift extension allows you to derive instances of the Lift typeclass, which makes it very easy to write expression splices using Template Haskell. In contrast to most derivable typeclasses, the Lift class does not live in base; it comes from the template-haskell package.
GHC has a number of mechanisms for automatically generating typeclass instances, most of them enabled via language extensions. Some extensions allow the deriving of one particular class; others are more general and can be used with any class. The DerivingStrategies extension, introduced in GHC 8.2, brings them all together into a single more cohesive idea by introducing two syntactic changes: First, a type definition can have multiple ‘deriving’ clauses, not just one. Second, each deriving clause may optionally specify a “deriving strategy” that specifies which deriving mechanism to use for the classes listed in that clause.
The DerivingVia GHC extension provides the ‘via’ deriving strategy, which lets your type copy typeclass instances from other types. The type providing the instances and the type receiving the instances have to be representationally equivalent – more or less the same, distinguished only by one or more layers of newtype definitions.
The GHC language extension called ExplicitForAll enables one fairly small, albeit useful, addition to Haskell’s syntax for writing type signatures: the ‘forall’ keyword. You don’t often need to be concerned with enabling this extension, because if you need forall, it’s probably because you’re using some other extension that enables it automatically, such as ScopedTypeVariables or RankNTypes.
An organized listing of the GHC extensions to the Haskell language.
When you enable the MagicHash GHC extension, two things change: First, the identifier naming rules are modified slightly so that names ending with one or more hash (#) characters are valid identifiers, which normally wouldn’t be allowed. Second, you can now write “unlifted literals” such as 3#.
The MultiWayIf extension introduces a kind of ‘if’ expression that allows more than two branches, using the same syntax as pattern guards.
These GHC language extensions extend the deriving mechanism specified in the Haskell Report by enabling automatic deriving of specific additional classes: DeriveFunctor, DeriveFoldable, DeriveTraversable, DeriveGeneric, DeriveLift, and DeriveDataTypeable.
‘Template Haskell’ is the name of both Haskell’s entire metaprogramming infrastructure as well as a specific GHC extension that enables a number of language features that support it. Most notably, enabling the TemplateHaskell extension allows you to write “splices”, that allow you to inject generated code into your code.
In standard Haskell, operator symbols may only be used at the value level. GHC expands the role of operators with the TypeOperators extension, which makes it possible to use an operator as the name of a type.
Haddock is the documentation tool for Haskell.
This section covers topics that aren’t about the Haskell language itself, but about software that helps you be more productive with it.
History of the ScopedTypeVariables GHC language extension.
You can use a combination of ScopedTypeVariables, PartialTypeSignatures, and typed holes to explore code, whether it’s code you’re trying to write yourself or a new library or codebase you’re trying to learn.
There is no “universal way to print anything” in Haskell, but there is usually something you can do in this situation. Here we discuss a variety of ways to print a value if there isn’t a Show instance available.
There are two kinds of names in Haskell: “Identifiers” and “operator symbols”. An identifier starts with a letter or underscore and consists of letters, numbers, underscore (_), and single quote (’). An operator symbol consists entirely of “symbol or punctuation” characters.
White space is syntactically significant in Haskell, and the parser can be persnickety about indentation. Many beginning Haskellers have been frustrated by parse errors and the difficulty of determining just what went wrong. Here we present an introduction to how Haskell uses indentation and white space.
Haskell resources for Java programmers.
Apart from the fiddly distinction regarding return type polymorphism, a major difference between an “algebra” and an “interface” is that algebras tend to be descriptive, and interfaces tend to be more prescriptive.
First we discuss “visitor pattern” and see some examples in Java, and then we look at comparable code in Haskell. We will see that the Java code using visitors bears a strong resemblance to what we call “sum types” or “tagged unions” in Haskell.
A monoid is a type together with a binary operation and an identity or neutral element. The operation must be “closed”, meaning its output has the same type as its operands, and it must be associative. The identity element must be a member of the same set and act as a neutral element with regard to that operation. Many sets have more than one such operation over them. Integers, for example, are monoids under both a “sum” and a “product” operation.
When you don’t specify a type for an expression, Hindley-Milner infers the most general, maximally-polymorphic type that your expression could possibly have. The designers of Haskell deemed that in some circumstances this leads to particularly unintuitive results, and so they invented a monomorphism restriction rule that places some limitation on the situations in which the compiler is allowed to infer a polymorphic type.
Nix is a general-purpose build tool, like a modern reinvention of Make that uses file hashes instead of timestamps. As Haskell fans we love it because the configuration language, a (mostly) pure lazy lambda calculus, has a familiar feel.
There are some reasons you might not want the entire contents of the prelude to be implicitly present everywhere: if you are a learner and you want to reimplement parts of base for exercise; if you are an opinionated expert and you dislike many of the things in Prelude; if you are using the RebindableSyntax extension. Here we discuss how to use either NoImplicitPrelude, import statement, or module mixins to remove the prelude from scope.
There are a lot of parsing libraries in Haskell. What’s more important to you: Giving informative error messages for invalid inputs, or speed? Do you need to run the parser incrementally? Do you want automatic backtracking?
The Haskell Phrasebook is a free quick-start Haskell guide comprised of a sequence of small annotated programs. It provides a cursory overview of selected Haskell features, jumping-off points for further reading, and recommendations to help get you writing programs as soon as possible.
An explanation of the different kinds of types in GHC Haskell, including the differences between primitive, unlifted, and unboxed types, the MagicHash language extension, and the meaning of levity polymorphism.
Profunctors are bifunctors that are contravariant in their first type argument and covariant in their second one. Make sure that you understand contravariance first. Then we just need to talk about bifunctors, and finally we will get to profunctors.
Haskell resources for Python programmers.
The primary role of a Python data class is to simply hold the values that were passed as constructor arguments. This feature strongly resembles Haskell datatypes, particularly when we use Haskell’s record syntax.
Decorator syntax refers to some syntactic sugar in Python that lets you simultaneously define a function
f and apply a function
g to the function you just defined.
f is called the “decorated” function, and
g is called the “decorator.” Here we look at several examples using decorators in Python, compare them to similar situations in Haskell, and discuss how lambdas let us achieve the same result without having a special syntax for decorators.
A Python iterator is a sort of sequence that, unlike a list, computes each subsequent value only as it is needed rather than computing the entire list all at once. In simple cases, Haskell’s list type (
) fulfills a similar role. This series compares Python iterators to Haskell’s list datatype, taking a deep dive into the
itertools library and the corresponding functions in the Haskell standard library.
The phrase “rigid type variable” shows up in several contexts in GHC error messages. Often, when it appears, it’s in a context where you know that the type variable it refers to is totally unconstrained, or parametrically polymorphic, and you may have found yourself wondering what is exactly is meant by “rigid”? How can something that could be anything be “rigid”? The phrase “rigid type variable” can be traced back at least to 2004, to a paper contrasting rigid types with “wobbly types”, that is, types that the compiler has to guess at. A later paper, published in 2006 suggested that the other name considered for rigid type was “user-specified type.”
A semigroup is a type together with a binary operation. The operation must be “closed”, meaning its output has the same type as its operands, and it must be “associative”:
x <> (y <> z) =
(x <> y) <> z. Many sets have more than one such operation over them. Integers, for example, are semigroups under both a “min” and a “max” operation.
A semiring is like a double monoid. That is, it’s a set equipped with two binary associative operations ⊕ and ⊗. The “addition” operation ⊕ is commutative, and its identity value is the annihilator for the “multiplication” operation ⊗. One familiar example is integers: Addition and multiplication are monoids, and the additive identity (0) is the multiplicative annihilator. We also look at some that might be less familiar but are also relevant to programming.
In many cases, Stack and Nix are considered competing tools rather than complementary ones. However, there are circumstances in which you want them to learn to play nice together. If you find yourself in that situation, here are some tips from the trenches, as it were, on using Stack’s Nix integration.
Here we look at two common Haskell libraries, text and bytestring, and addressing the frequently-asked question: “Why are there so many types of strings?” We’ll examine the differences between various string types, talk about what situations in which each is appropriate, and see what functions the libraries give us to convert among them.
Threads are concurrent flows of execution within one process. Haskell chooses to implement its own multithreading abstraction instead of simply using native OS threads directly, because OS threads are slower to initialize and have a greater memory cost. For applications written entirely in Haskell, there is no semantic difference between OS threads and Haskell threads, but there are some reasons to appreciate the distinction between the two. By default, Haskell programs only use a single OS thread. You must build with the
-threaded flag to enable multiple OS threads.
The Native GUI Clocks course will feature lessons for building native clock applications with several different Haskell GUI libraries. Lessons will use different libraries in order to highlight different aspects of them.
We walk through a common use case for the ‘transformers’ library and use it to illustrate type aliases, newtypes, and various approaches for typeclass deriving, using the GeneralizedNewtypeDeriving and DerivingVia GHC extensions.
Typed holes are a useful feature of GHC Haskell that allow you to replace expressions with holes in the form of underscores. Those holes provoke GHC into telling you the type of the hole as well as a list of valid hole fits, and those help you write your code.
An underscore character in Haskell code usually represents something we don’t care about or don’t know about – a wildcard, a hole, or a discarded result.
The course begins with two lessons on case expressions to ensure a solid foundation. From there, we write three functions for checking that inputs are valid passwords according to the rules of our system. The rest of the lessons iteratively expand on and refactor those functions into a small program that validates usernames and passwords, constructs a User if both are valid inputs, and returns pretty error messages if they are not. Along the way we learn about Monad and Applicative and how they are similar and different and how to use types to rethink our solutions to problems.
This course uses Haskell to explore what a web server is, starting from how we use sockets and the network library, and moving toward a foundation for higher-level libraries for building web applications. On the way, you will learn: what is a socket; how to read the HTTP specification; the difference between a strict ByteString, a lazy ByteString, and a byte string Builder; what “chunked transfer coding” means in HTTP, and what that has to do with lazy I/O; how to use Attoparsec to parse an HTTP request; how to use the Pipes library to parse streaming input.