Overview of the ecosystem
Disclaimer
This section is adapted from Gabriella Gonzalez' State of the Ecosystem, which is licensed here.
Some of the text has been cropped or modified.
Contributors
- Aaron Levin
- Alois Cochard
- Ben Kovach
- Benno FΓΌnfstΓΌck
- Carlo Hamalainen
- Chris Allen
- Curtis Gagliardi
- Deech
- David Howlett
- David Johnson
- Edward Cho
- Greg Weber
- Gregor Uhlenheuer
- Juan Pedro Villa Isaza
- Kazu Yamamoto
- Kevin Cantu
- Kirill Zaborsky
- Liam O'Connor-Davis
- Luke Randall
- Marcio Klepacz
- Mitchell Rosen
- Nicolas Kaiser
- Oliver Charles
- Pierre Radermecker
- Rodrigo B. de Oliveira
- Stephen Diehl
- Tim Docker
- Tran Ma
- Yuriy Syrovetskiy
- @bburdette
- @co-dan
- @ExternalReality
- @GetContented
- @psibi
- @newswim
Legend
π = Best in class: the best experience in any language
π₯ = Mature: suitable for most programmers
π± = Immature: acceptable for early-adopters
β = Undeveloped
π Compilers¶
Notable libraries:
parsec
/megaparsec
/attoparsec
/trifecta
/alex
+happy
- parsing librariesbound
/unbound
- manipulating bound variableshoopl
- optimizationuuagc
- attribute grammarsunification-fd
- fast structural unificationprettyprinter
- pretty-printingllvm-general
- LLVM 3.5 APIllvm-hs
- LLVM 5 API (actively maintained fork of llvm-general)language-
{ecmascript
|python
|c-quote
|lua
|java
|objc
|cil
} - parsers and pretty-printers for other languages
π Generic programming¶
This refers to automatically deriving algorithms for custom data types. Haskell is uniquely good at this:
discrimination
- fast, generic, linear-time discrimination and sortingoptparse-generic
- well-documented auto-generation of command-line parsers for custom types.generic-data
- deriving typeclass instances likeMonoid
automatically for custom datageneric-lens
- derive lenses and prisms for custom datatypes
π Single-machine Concurrency¶
Notable libraries:
stm
- Software transactional memoryunagi-chan
- High performance channelsasync
- Futures librarystreamly
- A streaming library offering high performance concurrency
Commentary
Haskell's concurrency runtime performs as well or better than other mainstream languages and is significantly easier to use due to the runtime support for software-transactional memory.
The best explanation of Haskell's threading module is the documentation in
Control.Concurrent
:
Concurrency is "lightweight", which means that both thread creation and context switching overheads are extremely low. Scheduling of Haskell threads is done internally in the Haskell runtime system, and doesn't make use of any operating system-supplied thread packages.
In Haskell, all I/O is non-blocking by default, so for example a web server will just spawn one lightweight thread per connection and each thread can be written in an ordinary synchronous style instead of nested callbacks like in Node.js.
The best way to explain the performance of Haskell's threaded runtime is to give hard numbers:
- The Haskell thread scheduler can easily handle millions of threads
- Each thread requires 1 kb of memory, so the hard limitation to thread count is memory (1 GB per million threads).
- Haskell channel overhead for the standard library (using
TQueue
) is on the order of one microsecond per message and degrades linearly with increasing contention - Haskell channel overhead using the
unagi-chan
library is on the order of 100 nanoseconds (even under contention) - Haskell's
MVar
(a low-level concurrency communication primitive) requires 10-20 ns to add or remove values (roughly on par with acquiring or releasing a lock in other languages)
Haskell also provides software-transactional memory, which allows programmers build composable and atomic memory transactions. You can compose transactions together in multiple ways to build larger transactions:
- You can sequence two transactions to build a larger atomic transaction
- You can combine two transactions using alternation, falling back on the second transaction if the first one fails
- Transactions can retry, rolling back their state and sleeping until one of their dependencies changes in order to avoid wasteful polling
A few other languages provide software-transactional memory, but Haskell's implementation has two main advantages over other implementations:
- The type system enforces that transactions only permit reversible memory modifications. This guarantees at compile time that all transactions can be safely rolled back.
- Haskell's STM runtime takes advantage of enforced purity to improve the efficiency of transactions, retries, and alternation.
Haskell is also the only language that supports both software transactional memory and non-blocking I/O.
Educational resources:
- Parallel and Concurrent Programming in Haskell
- Parallel and Concurrent Programming in Haskell - Software transactional memory
- Beautiful concurrency - a software-transactional memory tutorial
- Performance numbers for primitive operations - Latency timings for various low-level operations
Success Stories:
π Parsing / Pretty-printing¶
Parsing libraries:
megaparsec
- Modern, actively maintained fork ofparsec
attoparsec
- Extremely fast backtracking parserEarley
- Earley parsing embedded within the Haskell language. Parses all context-free grammars, even ambiguous ones, with no need to left factor. Returns all valid parses.trifecta
- Best error messages (clang
-style)parsers
- Interface compatible withattoparsec
,parsec
andtrifecta
which lets you easily switch between them. People commonly use this library to begin withtrifecta
orparsec
(for better error messages) then switch toattoparsec
when done for performancealex
/happy
- Likelexx
/yacc
but with Haskell integration
Commentary
Haskell parsing is extremely powerful. Recursive descent parser combinators are far-and-away the most popular parsing paradigm within the Haskell ecosystem, so much so that people use them even in place of regular expressions.
If you're not sure what library to pick, we generally recommend the megaparsec
library as a default well-rounded choice because it strikes a decent balance
between ease-of-use, performance, good error messages, and small dependencies.
attoparsec
deserves special mention as an extremely fast backtracking parsing
library. The speed and simplicity of this library will blow you away. The
main deficiency of attoparsec
is the poor error messages.
The pretty-printing front is also excellent. Academic researchers just really love writing pretty-printing libraries in Haskell for some reason.
Pretty-printing libraries:
prettyprinter
- Pretty-printing librarytext-format
- High-performance string formatting
Educational resources:
Success Stories:
π₯ Server-side web programming¶
Notable libraries:
aeson
- Parsing and generation of JSONwarp
/wai
- the low-level server and API that all server libraries share, with the exception ofsnap
scotty
- A beginner-friendly server framework analogous to Ruby's Sinatraspock
- Lighter than the "enterprise" frameworks, but more featureful than scotty (type-safe routing, sessions, conn pooling, csrf protection, authentication, etc)yesod
/yesod-*
/snap
/snap-*
/happstack-server
/happstack-*
- "Enterprise" server frameworks with all the bells and whistlesihp
- batteries-included web framework with a friendly and helpful community. The best choice when getting started with haskell.servant
/servant-*
- Library for type-safe REST servers and clients that might blow your mindgraphql-api
- Implement a GraphQL APIwebsockets
- Standalone websockets client and serverauthenticate
/authenticate-*
- Shared authentication librariesekg
/ekg-*
- Haskell service monitoringstm
- Software-transactional memorylucid
- Haskell DSL for building HTMLmustache
/karver
- Templating libraries
Commentary
The main features in this category that Haskell brings to the table are:
- Server stability
- Performance
- Ease of concurrent programming
- Excellent support for web standards
The strong type system and polished runtime greatly improve server stability and simplify maintenance. This is the greatest differentiator of Haskell from other backend languages, because it significantly reduces the total-cost-of-ownership. You should expect that you can maintain Haskell-based services with significantly fewer programmers than other languages, even when compared to other statically typed languages.
The greatest weakness of server stability is space leaks. The most
common solution that I know of is to use ekg
(a process monitor) to examine
a server's memory stability before deploying to production. The second most
common solution is to learn to detect and prevent space leaks with experience,
which is not as hard as people think.
Haskell's performance is excellent and currently comparable to Java. Both languages give roughly the same performance in beginner or expert hands, although for different reasons.
Where Haskell shines in usability is the runtime support for the following three features:
- software transactional memory (which differentiates Haskell from Go)
- lightweight threads that use non-blocking I/O (which differentiates Haskell from the JVM)
- garbage collection (which differentiates Haskell from Rust)
If you have never tried out Haskell's software transactional memory (STM), we highly recommend giving it a go, since it eliminates a large number of concurrency logic bugs. STM is far and away the most underestimated feature of the Haskell runtime.
Some web sites,services, and projects powered by Haskell:
- Facebook's spam filter: Sigma
- IMVU's REST API
- Utrecht's bicycle parking guidance system
- elm-lang.org
- glot.io
- The Perry Bible Fellowship
- Silk
- Shellcheck
- instantwatcher.com
- markup.rocks
- ZoomHub (Code)
- PostgREST - Generates a REST API for a Postgres database
- Hasura
- Mercury
Success Stories:
- Fighting spam with Haskell - Haskell in production, at scale, at Facebook
- IMVU Engineering - What it's like to use Haskell
- Haskell-based Bicycle Parking Guidance System in Utrecht
- Mio: A High-Performance Multicore IO Manager for GHC
- The Performance of Open Source Applications - Warp
- Optimising Garbage Collection Overhead in Sigma
- instantwatcher.com author comments on rewrite from Ruby to Haskell - [1] [2]
- A lot of websockets in Haskell - A load test showing that a Haskell server can handle 500K connections in 10 GB of memory. The load tester requires more resources than the server
Educational resources:
- Beautiful concurrency - a software-transactional memory tutorial
- The Yesod book
- The Servant tutorial
- Overview of Happstack
- IHP Guide
- IHP Casts
Notable hosting platforms:
π₯ Testing¶
Notable libraries:
QuickCheck
- property-based testingdoctest
- tests embedded directly within documentationfree
- Haskell's abstract version of "dependency injection"hspec
- Testing library analogous to Ruby's RSpecHUnit
- Testing library analogous to Java's JUnittasty
- Combination unit / regression / property testing libraryhedgehog
- property-based testing with integrated shrinkingHTF
- Preprocessor based unit testing with various output formats
Commentary
There are a few places where Haskell is the clear leader among all languages:
- property-based testing
- mocking / dependency injection
Haskell's QuickCheck
is the gold standard which all other property-based
testing libraries are measured against. The reason QuickCheck
works so
smoothly in Haskell is due to Haskell's type class system and purity. The type
class system simplifies automatic generation of random data from the input type
of the property test. Purity means that any failing test result can be
automatically minimized by rerunning the check on smaller and smaller inputs
until QuickCheck
identifies the corner case that triggers the failure.
Haskell also supports most testing functionality that you expect from other languages, including:
- standard package interfaces for testing
- unit testing libraries
- test result summaries and visualization
Educational resources:
π₯ Data structures and algorithms¶
Notable libraries:
vector
- High-performance arrayscontainers
- High-performanceMap
s,Set
s,Tree
s,Graph
s,Seq
sunordered-containers
- High-performanceHashMap
s, HashSetsaccelerate
/accelerate-*
- GPU programmingmassiv
/repa
/repa-*
- parallel shape-polymorphic arraysdiscrimination
- Efficient linear-time sorting for user-defined datatypesalgebraic-graphs
Commentary
Haskell primarily uses persistent data structures, meaning that when you "update" a persistent data structure you just create a new data structure and you can keep the old one around (thus the name: persistent). Haskell data structures are immutable, so you don't actually create a deep copy of the data structure when updating; any new structure will reuse as much of the original data structure as possible.
The Notable libraries sections contains links to Haskell collections libraries that are heavily tuned. You should realistically expect these libraries to compete with tuned Java code. However, you should not expect Haskell to match expertly tuned C++ code.
The selection of algorithms is not as broad as in Java or C++ but it is still pretty good and diverse enough to cover the majority of use cases.
π₯ Benchmarking¶
Notable libraries:
criterion
gauge
offers a similar feature set ascriterion
but has much fewer dependenciestasty-bench
even lighter thangauge
with support for comparing benchmarks
Commentary
This boils down exclusively to the criterion
library, which was done so well
that nobody bothered to write a competing library. Notable criterion
features include:
- Detailed statistical analysis of timing data
- Beautiful graph output: (Example)
- High-resolution analysis (accurate down to nanoseconds)
- Customizable HTML/CSV/JSON output
- Garbage collection insensitivity
Educational resources:
π₯ Unicode¶
Notable libraries:
text
text-icu
unicode-transforms
β Unicode normalization
Commentary
Haskell's Unicode support is excellent. Just use the text
and text-icu
libraries, which provide a high-performance, space-efficient, and easy-to-use
API for Unicode-aware text operations.
Note that there is one big catch: the default String
type in Haskell is
inefficient. You should always use Text
whenever possible.
π₯ Stream programming¶
Notable libraries:
conduit
/io-streams
/pipes
/streaming
/streamly
- Stream programming librariesmachines
- Networked stream transducers library
Commentary
Haskell's streaming ecosystem is mature. Probably the biggest issue is that there are too many good choices (and a lot of ecosystem fragmentation as a result), but each of the streaming libraries listed below has a sufficiently rich ecosystem including common streaming tasks like:
- Network transmissions
- Compression
- External process pipes
- High-performance streaming aggregation
- Concurrent streams
- Incremental parsing
Educational resources:
π₯ Serialization¶
Notable libraries:
Commentary
Haskell's serialization libraries are reasonably efficient and very easy to use. You can easily automatically derive serializers/deserializers for user-defined data types and it's very easy to encode/decode values.
Haskell's serialization does not suffer from any of the gotchas that object-oriented languages deal with (particularly Java/Scala). Haskell data types don't have associated methods or state to deal with so serialization/deserialization is straightforward and obvious. That's also why you can automatically derive correct serializers/deserializers.
Serialization performance is pretty good. You should expect to serialize data at a rate between 100 Mb/s to 1 Gb/s with careful tuning. Serialization performance still has about 3x-5x room for improvement by multiple independent estimates. See the "Faster binary serialization" link below for details of the ongoing work to improve the serialization speed of existing libraries.
Educational resources:
- Benchmarks of several popular serialization libraries
- Faster binary serialization / Better, faster binary serialization - Slides on serialization efficiency improvements
π₯ IDE support¶
The Haskell Language Server provides IDE support for editors which support Microsoft's Language Service Protocol (LSP). The easiest of these to use is VSCode, but other choices like vim will work.
The Haskell Language Server is included as part of Haskell's installer, GHCup.
π₯ Support for file formats¶
Notable libraries:
aeson
- JSON encoding/decodingcassava
/sv
- CSV encoding/decodingyaml
- YAML encoding/decodingHsYAML
- pure Haskell YAML 1.2 parserxml
- XML encoding/decodingtomland
- TOML encoding/decoding
Commentary
Haskell supports all the common domain-independent serialization formats (i.e. XML/JSON/YAML/CSV). For more exotic formats Haskell won't be as good as, say, Python (which is notorious for supporting a huge number of file formats) but it's so easy to write your own quick and dirty parser in Haskell that this is not much of an issue.
π₯ Logging¶
fast-logger
- High-performance multicore logging systemhslogger
- Logging library analogous to Python'slogging
librarymonad-logger
- add logging with line numbers to your monad stack. Uses fast-logger under the hood.katip
- Structured logginglog
- Logging system with ElasticSearch, PostgreSQL and stdout sinks.co-log
- Composable contravariant comonadic logging library.
π₯ Code formatting¶
Haskell has tools for automatic code formatting:
ormolu
- More opinionated formatting tool that uses GHC's own parserfourmolu
- likeormolu
but with configurabilitystylish-haskell
- Less opinionated code formatting tool that mostly formats imports, language extensions, and data type definitions
π₯ Scripting¶
Notable libraries:
optparse-applicative
/cmdargs
- command-line argument parsingoptparse-generic
- well-documented auto-generation of command-line parsers for custom types.shelly
/turtle
/shellmet
- scripting librarieshaskeline
- a complete Haskell implementation ofreadline
for console buildingprocess
- low-level library for sub-process managementansi-terminal
- de facto standard cross-platform terminal library (works on Windows as well)brick
- terminal user interfaces (TUIs)path
/path-io
- type safe handling of file pathshttp-client
/http-client-*
/req
/req-*
/wreq
- HTTP clients
Commentary
Haskell's biggest advantage as a scripting language is that Haskell is the most widely adopted language that supports global type inference. Many languages support local type inference (such as Rust, Go, Java, C#), which means that function argument types and interfaces must be declared but everything else can be inferred. In Haskell, you can omit everything: all types and interfaces are completely inferred by the compiler (with some caveats, but they are minor).
Global type inference gives Haskell the feel of a scripting language while still providing static assurances of safety. Script type safety matters in particular for enterprise environments where glue scripts running with elevated privileges are one of the weakest points in these software architectures.
The second benefit of Haskell's type safety is ease of script maintenance. Many scripts grow out of control as they accrete arcane requirements and once they begin to exceed 1000 LOC they become difficult to maintain in a dynamically typed language. People rarely budget sufficient time to create a sufficiently extensive test suite that exercises every code path for each and every one of their scripts. Having a strong type system is like getting a large number of auto-generated tests for free that exercise all script code paths. Moreover, the type system is more resilient to refactoring than a test suite.
However, the language is also usable even for simple one-off disposable scripts. These Haskell scripts are comparable in size and simplicity to their equivalent Bash or Python scripts. This lets you easily start small and finish big.
Haskell has one advantage over many dynamic scripting languages, which is that Haskell can be compiled into a native and statically linked binary for distribution to others.
Haskell's scripting libraries are feature complete and provide all the niceties that you would expect from scripting in Python or Ruby, including features such as:
- rich suite of Unix-like utilities
- advanced sub-process management
- POSIX support
- light-weight idioms for exception safety and automatic resource disposal
Some command-line tools written in Haskell:
Educational resources:
π± Data science¶
Notable libraries:
diagrams
/diagrams-*
- Vector graphics libraryihaskell
- Haskell backend to IPythonhmatrix
- BLAS / LAPACK wrapperHaskellR
- Mix Haskell and R code in Jupyter notebooksSparkle
- Haskell-to-Spark bridgecassava
- CSV encoding and decodingFrames
- Haskell data analysis tool analogous to Python'spandas
statistics
hvega
- Plots via JS: quite powerful and well documentedChart
/Chart-*
- Charting library
Commentary
Haskell data science can take advantage of other data science ecosystems via the
HaskellR
and
Sparkle
projects. HaskellR
is a
Haskell-to-R bridge with Jupyter notebook integration, which lets you take
advantage of the broad R ecosystem while benefiting from the speed and type
safety of Haskell. Sparkle
is a Haskell-to-Spark bridge which lets you
interface with the Spark subset of the Java/Scala data science ecosystem.
However, to get a Mature rating Haskell data science needs to be able to
stand alone without depending on other programming language ecosystems.
If you restrict yourself to just the Haskell ecosystem then choices are more limited.
The Haskell analog of Python's NumPy
is the hmatrix
library, which provides Haskell
bindings to BLAS, LAPACK. hmatrix
's main limitation is that the API is a bit
clunky, but all the tools are there.
Haskell's charting story is okay. Most charting APIs tend to be large, the types are a bit complex, and they have a very large number of dependencies.
Fortunately, Haskell does integrate into IPython so you can use Haskell within an IPython shell or an online notebook. For example, there is an online "IHaskell" notebook that you can use right now located here:
- IHaskell notebook - Click on "Welcome to Haskell.ipynb"
If you want to learn more about how to setup your own IHaskell notebook, visit this project:
The closest thing to Python's pandas
is the frames
library.
One Haskell library that deserves honorable mention here is the diagrams
library which lets you produce complex data visualizations very easily if
you want something a little bit fancier than a chart. Check out the diagrams
project if you have time:
Areas for improvement:
- Smooth user experience and integration across all of these libraries
- Simple types and APIs. The data science programmers I know dislike overly complex or verbose APIs
- Beautiful data visualizations with very little investment
π± Numerical programming¶
Notable libraries:
accelerate
/accelerate-*
- GPU programmingvector
- high-performance arraysmassiv
/repa
/repa-*
- parallel shape-polymorphic arrayshmatrix
/hmatrix-*
- Haskell's BLAS / LAPACK wrapperad
- automatic differentiation
Commentary
Haskell's numerical programming story is not ready, but steadily improving.
The biggest issues that the ecosystem faces are:
- Really clunky matrix library APIs
- Fickle rewrite-rule-based optimizations
When the optimizations work they are amazing and produce code competitive with C. However, small changes to your code can cause the optimizations to suddenly not trigger and then performance drops off a cliff.
There is one Haskell library that avoids this problem entirely: accelerate
generates LLVM and CUDA code at runtime and does not rely on Haskell's optimizer for code generation, which side-steps
the problem. accelerate
has a large set of supported algorithms that you
can find by just checking the library's reverse dependencies:
Success Stories:
- Exploiting vector instructions with generalized stream fusion
- Type-safe Runtime Code Generation: Accelerate to LLVM
Educational Resources:
π± Front-end web programming¶
Notable libraries:
- reflex / reflex-dom - Functional reactive programming library for the front end
- miso a small "isomorphic" front-end framework featuring a virtual-dom, inspired by Elm, Redux and Bobril.
Commentary
This boils down to Haskell's ability to compile to JavaScript and WASM. Upcoming GHC versions will allow compilation to both, but for now the technology is experimental.
There are two Haskell-like languages for front-end programming: elm
and purescript
.
These are both used in production today and have equally active maintainers and
communities of their own. purescript
in particular is extremely similar to
Haskell.
Areas for improvement:
- lack of clear story for smooth integration with existing JavaScript projects
- lack of educational resources targeted at non-experts explaining how to translate existing front-end programming idioms to Haskell
- lack of well-maintained and polished Haskell libraries for front-end programming
- lack of documentation for
ghcjs
ecosystem. There's not even a basic tutorial on how to actually useghcjs
Notable Haskell-to-JavaScript compilers:
π± Distributed programming¶
Notable libraries:
glue-core
/glue-ekg
/glue-example
- Service toolkit supportinghaxl
- Facebook library for efficient batching and scheduling of concurrent data accessdistributed-process
/distributed-process-*
- Haskell analog to Erlanghadron
- Haskell wrapper aroundhadoop
amazonka
/amazonka-*
- Auto-generated bindings to the entire Amazon Web Services SDKgogol
/gogol-*
- Auto-generated bindings to the entire Google Cloud Platformtransient
- composable primitives for concurrency / parallelism / distributed computing
Commentary
For distributed service architectures Haskell is catching up to its peers with service toolkit libraries, but for distributed computation Haskell still lags behind.
There has been a lot of work in replicating Erlang-like functionality in Haskell through the Cloud Haskell project, not just in creating the low-level primitives for code distribution / networking / transport, but also in assembling a Haskell analog of Erlang's OTP. Work on the higher-level libraries seems to have stopped, but the low-level libraries are still good for distributing computation.
Areas for improvement:
- More analytics libraries needed. Haskell has no analog of
scalding
orspark
. The most we have is just a Haskell wrapper aroundhadoop
- A polished consensus library (i.e. a high quality Raft implementation in Haskell) needed.
π± Standalone GUI applications¶
Notable libraries:
brick
- Terminal UI based on vty packagethreepenny-gui
- Framework for local apps that use the web browser as the interfacegi-gtk
and various other bindings such as GStreamer audio/video - GTK+ (and more generally, GObject) bindings done right (autogenerated using GObject Introspection, hencegi
)wx
- wxWidgets bindingsX11
- X11 bindingshsqml
- A Haskell binding for Qt Quick, a cross-platform framework for creating graphical user interfaces.fltkhs
- A Haskell binding to FLTK. Easy install/use, cross-platform, self-contained executables.FregeFX
- Frege bindings to Java FX (Frege is essentially the Haskell for the JVM)typed-spreadsheet
- Library for building composable interactive forms
Commentary
Most Haskell GUI libraries are wrappers around toolkits written in other
languages (such as GTK+ or Qt).
However, the Haskell bindings to GTK+ have a strongly imperative feel to them.
The way you do everything is communicating between callbacks by mutating
IORef
s. Also, you can't take extensive advantage of Haskell's awesome
threading features because the GTK+ runtime is picky about what needs to happen
on certain threads.
There still isn't a Haskell binding to a widget toolkit that doesn't have some sort of setup issues with the toolkit.
My impression is that most Haskell programmers interested in applications programming have collectively decided to concentrate their efforts on improving Haskell web applications instead of standalone GUI applications. Honestly, that's probably the right decision in the long run.
Another post that goes into more detail about this topic is this post written by Keera Studios:
Areas for improvement:
- A GUI toolkit binding that is maintained, comprehensive, and easy to use
- Polished GUI interface builders
Some example applications:
Educational resources:
π± Machine learning¶
Notable libraries:
hasktorch
- Haskell bindings to libtorch which is the C++ API for PyTorchad
- Automatic differentiation, used as a substrate for many Haskell machine learning projectsbackprop
- AD for heterogenous typesad-delcont
grenade
- Machine learning library implemented in Haskell with a BLAS/LAPACK backend and a high-level type-based APItensorflow
- Haskell bindings to Google'stensorflow
projectarrayfire
- Haskell bindings to ArrayFire
Commentary
There are two approaches to using machine learning in Haskell:
- Use a Haskell binding to an implementation in another language
- Use a machine learning library implemented in Haskell
You will most likely want to check out Haskell bindings to the libtorch
library if you are interested in the first approach.
Also, Tweag.io has released Sparkle
, a Haskell integration with Spark. This
enables the use of MLib from Haskell. MLib is widely used in the industry
for machine learning. Sparkle itself is fairly new.
π± Game programming¶
Notable libraries:
gloss
- Simple graphics and game programming for beginnersYampa
- A reactive programming library which has been used to implement games in a reactive style- Code World - Similar to
gloss
, but you can try it in your browser vulkan
- Low-level Vulkan bindingsgl
- Comprehensive OpenGL bindingsSDL
/SDL-*
/sdl2
- Bindings to the SDL librarySFML
- Bindings to the SFML libraryquine
- Github project with cool 3D demosGPipe
- Type-safe OpenGL API that also lets you embed shader code directly within Haskell. See the GPipe wiki to learn more
Commentary
Haskell is a garbage collected language, so Haskell is more appropriate for the scripting / logic layer of a game but not suitable manipulating a large object graph or for implementing a high-performance game engine due to the risk of introducing perceptible pauses due to GC pauses. For simple games you can realistically use Haskell for the entire stack.
Examples of games that could be fully implemented in Haskell:
- Casual games
- Turn-based strategy games
- Adventure games
- Platform / side-scrolling games
- First-person shooter
Examples of games that are difficult to implement at all in Haskell:
- Real-time strategy games
- MMORPGs
Haskell has SDL, OpenGL, and Vulkan bindings, which are actually quite good, but that's about it. You're on your own from that point onward. There is not a rich ecosystem of higher-level libraries built on top of those bindings. There is some work in this area, but nothing production quality or easy to use.
The primary reason for the immature rating is the difficulty of integrating Haskell with existing game platforms, which often are biased towards a particular language or toolchain. The only game platform where Haskell has no issues is native binaries for desktop games. For the web, you must compile to JavaScript, which is doable. For mobile games on Android you have to cross compile and interface the Haskell logic with Android through JNI + Haskell's foreign function interface. For console games, you have no hope.
Areas for improvement:
- Improve the garbage collector and benchmark performance with large heap sizes
- Provide higher-level game engines
- Improve distribution of Haskell games on proprietary game platforms
Educational resources:
π± ARM processor support¶
Commentary
On hobbyist boards like the Raspberry Pi its possible to compile Haskell code with GHC. There are limitations; some libraries have problems on the arm platform, and GHCi only works on newer compilers. Cross compiling doesn't work with template Haskell. Stack and other large projects can take more than 1g of memory to compile.
However, if the Haskell code builds, it runs with respectable performance on these machines.
Arch (Banana Pi)
update 2016-02-25:
- installed today from pacman, current versions are GHC 7.10.3 and cabal-install 1.22.6.0
- a compatible version of llvm also installed automatically.
- GHCi passes hello world test; cabal/GHC compiled a modest project normally.
Raspian (Raspberry Pi, pi2, others)
- current version: GHC 7.4, cabal-install 1.14
- GHCi doesn't work.
Debian Jesse (Raspberry Pi 3)
- works with:
ghc-7.10.3
andstack-1.1.2
- Requires
llvm
version 3.5.2 or higher. Do not use thellvm-3.5
provided by default in the Jessie package distribution
Arch (Raspberry Pi 2)
- current version 7.8.2, but llvm is 3.6, which is too new.
- downgrade packages for llvm not officially available.
- with llvm downgrade to 3.4, GHC and GHCi work, but problems compiling yesod, scotty.
- compiler crashes, segfaults, etc.
π± Computer Vision¶
Notable libraries:
Commentary
The largest real world Haskell usage of computer vision is LumiGuide, which
powers municipal bicycle detection and guidance systems in Amsterdam. They
maintain OpenCV
bindings in their haskell-opencv
library.
There are some interesting projects which try to tackle computer vision in a
purely functional manner. cv-combinators
, easyVision
, and Zef
are some
examples.
There are Haskell bindings for OpenCV available via HOpenCV
which has bindings
for versions up to OpenCV 2.0
. A fork maintained by Anthony Cowley has bindings
available for versions up to OpenCV 2.4
, but it pretty much stops there.
Currently, OpenCV 3.0
has been released, and there are no Haskell bindings
covering it.
Success Stories:
π± Mobile apps¶
Commentary
This greatly lags behind using languages that are natively supported by the mobile platform (i.e. Java for Android or Objective-C / Swift for iOS).
However, one route is to compile Haskell to a supported language. For example, you can compile Haskell to Java using Eta to port Haskell games to Android.
Educational resources:
π± Databases and data stores¶
Notable libraries:
mysql-haskell
/mysql-simple
- MySQL bindingspostgresql-simple
- Postgres bindingspersistent
- Database-agnostic ORM that supports automatic migrationsesqueleto
/relational-record
/opaleye
- type-safe APIs for building well-formed SQL queriesacid-state
- Simple ACID data store that saves Haskell data types nativelyaws
- Bindings to Amazon DynamoDBhedis
- Bindings to Redisgroundhog
- A nice datatype to relational mapping library, similar to ORMshasql
- An efficient PostgreSQL driver and a flexible mapping API based on the binary protocol
Commentary
The "Immature" ranking is based on the lack of bindings to commercial databases like Microsoft SQL server and Oracle. So whether or not Haskell is right for you probably depends heavily on whether there are bindings to the specific data store you use.
π± Debugging¶
Educational resources:
- GHC Manual - Profiling chapter - Read the whole thing; you will thank me later
- Debugging runtime options - See the
+RTS -xc
flag which adds stack traces to all exceptions (requires profiling enabled) GHC.Stack
- Programmatic access to the call stack- Pinpointing space leaks in big programs
- Real World Haskell - Profiling and Optimization
- The GHCi Debuggger - Manual for GHCi-based breakpoints and single-stepping
- Parallel and Concurrent Programming in Haskell - Debugging, Tuning, and Interfacing with Foreign Code - Debugging concurrent programs
- Haskell wiki - ThreadScope
Commentary
The main Haskell debugging features are:
- Memory and performance profiling
- Stack traces
- Source-located errors, using the
assert
function - Breakpoints, single-stepping, and tracing within the GHCi REPL
- Informal
printf
-style tracing usingDebug.Trace
- ThreadScope
π± Hot code loading¶
Notable libraries:
essence-of-live-coding
dyre
/halive
- Program reinitialization with saved staterapid
- Code reloading withinghci
that persists state across reloadsplugins
/hint
- Runtime compilation and linking
π± Systems / embedded programming¶
Educational resources:
Commentary
Systems programming here means: programs where speed, memory layout, and latency really matter.
Haskell fares really poorly in this area because:
- The language is garbage collected, so there are no latency guarantees
- Executable sizes are large
- Memory usage is difficult to constrain (thanks to space leaks)
- Haskell has a large and unavoidable runtime, which means you cannot easily embed Haskell within larger programs
- You can't easily predict what machine code that Haskell code will compile to
Typically people approach this problem from the opposite direction: they write the low-level parts in C or Rust and then write Haskell bindings to the low-level code.
It's worth noting that there is an alternative approach which is Haskell DSLs that are strongly typed that generate low-level code at runtime. This is the approach championed by the company Galois.
Notable libraries:
Created: February 8, 2023
Commentary
Haskell originated in academia, and most languages of academic origin (such as the ML family of languages) excel at compiler-related tasks for obvious reasons. As a result the language has a rich ecosystem of libraries dedicated to compiler-related tasks, such as parsing, pretty-printing, unification, bound variables, syntax tree manipulations, and optimization.
Some compilers written in Haskell:
Elm
Purescript
Idris
Agda
Pugs
(the first Perl 6 implementation)ghc
(self-hosting)frege
(very similar to Haskell, also self-hosting)hython
(a Python3 interpreter written in Haskell)Lasca
(a small Scala-like language with global type inference and optional dynamic mode on LLVM backend)verve
- Functional language with object-oriented supportsixten
- Haskell/Idris-style language with a focus on precise and efficient memory layoutcarp
- An efficient, statically typed Lisp with ownership tracking.unison
- A purely functional distributed programming language with algebraic effects.oden
(no longer in active development)Educational resources:
Success stories: