Skip to content
Published on

Modern Haskell 2026 — GHC 9.10 / 9.12 / GHCup / Cabal 3.14 / Stack / IHP / Servant / Effectful / Pandoc / Cardano Deep Dive

Authors

Prologue — People still use Haskell in 2026

Every year someone asks: "Haskell? People still use that?"

Yes. And quite seriously.

  • GitHub wrote Semantic in Haskell; part of code search infrastructure runs on it.
  • Cardano is IOHK / IOG's Plutus smart-contract platform, and the core node is all Haskell.
  • Mercury Bank, Channable, Tweag, IOG, Standard Chartered, Anduril, Wire, Hasura run production Haskell codebases.
  • Pandoc — John MacFarlane's document converter — is the de facto standard in academia and publishing. Your Markdown-to-PDF pipeline likely passes through it.
  • ShellCheck, xmonad, darcs, postgrest, PureScript, the Elm 0.19 compiler (2018), dhall, Agda, Idris are Haskell too.

In the 2010s the real enemy was not "Haskell is hard". It was that the build tooling was split between Cabal and Stack, and both were subtly broken in different ways. What does that look like in 2026?

Answer: GHCup manages both well at the same time. So the "I got a Cabal file but they sent it from Stack and it does not build" experience is mostly gone. And GHC itself got another step faster in 9.10 and 9.12 thanks to modular compilation and better multi-core scheduling.

This article walks the 2026 Haskell stack in one breath. Compiler, build tools, full-stack web frameworks, effect libraries, ORMs, parsers, JSON, tests, formal verification, ML, document conversion, and the people behind it all.


1. Modern Haskell 2026 — The GHC 9.x era

One picture of the landscape.

                Modern Haskell 2026 stack

[install]        GHCup (recommended) -> ghc / cabal / stack / hls
[compiler]       GHC 9.10 (2024-05) / 9.12 (2024-12)
[build]          Cabal 3.14   |   Stack (LTS 22.x, Stackage)
[packages]       Hackage (all)  |  Stackage (curated LTS)

[full-stack web] IHP (Rails-style, digitally induced)
[web API]        Servant (typed HTTP DSL)
[other web]      Yesod / Snap / Scotty / Spock

[effects]        Effectful (mtl successor, 2026 default)
                 Polysemy / fused-effects / Bluefin

[ORM]            Persistent / Beam / Esqueleto

[parser]         Megaparsec / Attoparsec / Earley
[JSON]           Aeson
[strings/bytes]  text / bytestring / vector

[testing]        hedgehog (property) / tasty / hspec / QuickCheck
[verification]   Liquid Haskell (refinement types)

[ML]             Hasktorch (libtorch bindings)
[docs]           Pandoc (John MacFarlane)

[production]     GitHub / Cardano / Mercury / IOG /
                 Hasura / Anduril / Channable / Tweag

That is the 2026 Haskell map. Let us walk each box.


2. GHC 9.10 (2024-05) / 9.12 (2024-12)

GHC (Glasgow Haskell Compiler) is the Haskell reference implementation. For all practical purposes, the only industrial implementation.

GHC 9.10 (May 2024)

  • GHC2024 language edition — a year-stamped bundle of language extensions. Just write default-language: GHC2024 and LambdaCase, DataKinds, DerivingStrategies, DisambiguateRecordFields, ExplicitNamespaces, MonoLocalBinds, RoleAnnotations, ScopedTypeVariables are on by default.
  • Linear types (-XLinearTypes) matured — central to functional resource tracking.
  • GHC Proposals 511 — better type signatures inside let.
  • JavaScript backend stabilized — wasm32 and javascript backends officially supported.
  • Runtime system (GC, threaded RTS) tuning — -A default tweaks, better cold-cache numbers on 64-bit.

GHC 9.12 (December 2024)

  • CapiFFI improvements — safer interfaces for header macros.
  • OrPatterns extension — combine several constructors with | in pattern matching.
  • NamedDefaults — declare default class instances explicitly.
  • MultilineStrings — triple-quoted multi-line strings, familiar to users of other languages.
  • Type inference consistency — polymorphic variables become ambiguous less often.
  • Build performance — roughly 5-10 percent shorter compile time on average.
-- GHC 9.12 MultilineStrings + OrPatterns
{-# LANGUAGE MultilineStrings #-}
{-# LANGUAGE OrPatterns #-}

greeting :: String
greeting = """
  Hello,
  modern Haskell 2026.
  """

classify :: Int -> String
classify n = case n of
  (0 | 1 | 2) -> "small"
  (3 | 4 | 5) -> "medium"
  _           -> "large"

Which version to pick

  • New project: GHC 9.10.x — most balanced. HLS / Stack LTS / IHP / Servant all first-class.
  • Adventurer: GHC 9.12.x — if you want the new syntax (MultilineStrings, OrPatterns).
  • Enterprise / long dependency tree: GHC 9.8.x — slightly more conservative.
  • Legacy: below GHC 9.6 — no reason to start fresh in 2026.

Around 2020 the typical Haskell install story was "install Stack and that is it". Cabal users installed separately and the two did not quite get along.

In 2026, GHCup is the officially recommended installer. Run the one-line script from haskell.org/ghcup and it pulls GHC, Cabal, Stack, and HLS (Haskell Language Server).

# Official one-line install
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

# Or Windows PowerShell
# Set-ExecutionPolicy Bypass -Scope Process -Force
# Invoke-WebRequest ... ghcup-windows-... .ps1 | Invoke-Expression

After install, run ghcup tui for a text-mode UI where you can pick which GHC / Cabal / Stack / HLS versions to install or remove.

ghcup install ghc 9.10.1
ghcup install ghc 9.12.1
ghcup set ghc 9.10.1            # set 9.10 as the system default
ghcup install cabal 3.14.1.0
ghcup install hls 2.9.0.0       # Haskell Language Server (LSP)
ghcup install stack 3.1.1
ghcup list                       # installed and available versions

The key value of GHCup is multiple GHC versions side by side on the same host. It picks the right one automatically from cabal.project or stack.yaml.

Note: macOS and Linux use that script as standard. Windows GHCup installs natively rather than via Chocolatey. WSL users can use the same script.


4. Cabal 3.14 / Stack — the build tools

If GHC is the compiler, Cabal and Stack are the package and project managers on top of it.

Cabal 3.14

Cabal is actually two things.

  1. The Cabal library — parses *.cabal files and builds dependency graphs.
  2. The cabal-install CLI — uses that library; usually what we call "cabal".

Cabal 3.14 (late 2024) brings:

  • cabal repl multi-component support — library, executable, test suite in one REPL.
  • Faster dependency solver in cabal-install — noticeable on large dependency trees.
  • cabal.project.local precedence clarified.
  • Reproducible buildsindex-state pinning is more stable.
-- my-app.cabal (Cabal 3.14)
cabal-version:      3.14
name:               my-app
version:            0.1.0.0
synopsis:           A sample modern Haskell app
license:            BSD-3-Clause
build-type:         Simple

common warnings
  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns

library
  import:           warnings
  exposed-modules:  MyApp
                    MyApp.Server
  build-depends:    base ^>= 4.20
                  , servant ^>= 0.20
                  , servant-server ^>= 0.20
                  , warp ^>= 3.4
                  , aeson ^>= 2.2
                  , text ^>= 2.1
  hs-source-dirs:   src
  default-language: GHC2024

executable my-app
  import:           warnings
  main-is:          Main.hs
  build-depends:    base, my-app
  hs-source-dirs:   app
  default-language: GHC2024

test-suite my-app-test
  import:           warnings
  type:             exitcode-stdio-1.0
  main-is:          Spec.hs
  build-depends:    base, my-app, hspec ^>= 2.11, tasty ^>= 1.5
  hs-source-dirs:   test
  default-language: GHC2024

Stack

Stack started at FP Complete and is now maintained by the community under Haskell Foundation. The key difference from Cabal is that Stack defaults to a curated Stackage LTS snapshot.

# stack.yaml
resolver: lts-22.30  # Stackage LTS — packages tested together
packages:
  - .
extra-deps: []

Stackage LTS ships weekly minor releases and a new major every six months. The promise is "these packages build together and their tests pass together".

Which tool

  • New project, fast: Stack (Stackage LTS) — fewer dependency-conflict surprises.
  • Library / mainstream OSS: Cabal — direct Hackage publishing is natural.
  • Both: most large projects keep both cabal.project and stack.yaml.

In 2026, the Cabal camp moved faster, but Stack's "low-noise" UX is still attractive.


5. Hackage / Stackage — the package ecosystem

Hackage

hackage.haskell.org — the central Haskell package repository. Around 18,000 packages in 2026. Anyone can publish; versions follow PVP (Package Versioning Policy), similar to SemVer.

cabal update                     # refresh Hackage index
cabal install --installdir=./bin pandoc
cabal info aeson                 # package metadata

Stackage

stackage.org — a curation layer on top of Hackage, split into LTS and Nightly.

  • LTS-22.x (late 2024) — GHC 9.8 / 9.10 bundles
  • LTS-23.x (mid 2025) — GHC 9.10 / 9.12 bundles
  • Nightly — built daily, freshest set

Why Stackage matters: "package X conflicts with Y" is filtered out at the curation step. A library author can write resolver: lts-22.30 in stack.yaml and every package in that bundle builds together.


6. IHP (Integrated Haskell Platform) — the full-stack web

ihp.digitallyinduced.com — a full-stack web framework by Germany's digitally induced GmbH. The goal is to give Haskell a Rails / Phoenix / Laravel-class experience.

IHP philosophy

  • Convention over configuration — follow the directory layout and naming and you write less code.
  • Type-safe — router, forms, DB queries, views are tied together by types.
  • Dev tooling — dev server, migration GUI (IHP IDE), code generators.
# New IHP project
nix-shell -p ihp-new --run "ihp-new my-blog"
cd my-blog
./start                          # http://localhost:8000

IHP model example

-- Application/Schema.sql (defined directly in SQL)
CREATE TABLE posts (
    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
    title TEXT NOT NULL,
    body TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
);

-- Web/Controller/Posts.hs (lightly edited from the generator)
module Web.Controller.Posts where
import Web.Controller.Prelude
import Web.View.Posts.Index

instance Controller PostsController where
    action PostsAction = do
        posts <- query @Post |> fetch
        render IndexView { .. }
-- Web/View/Posts/Index.hs
module Web.View.Posts.Index where
import Web.View.Prelude

data IndexView = IndexView { posts :: [Post] }

instance View IndexView where
    html IndexView { .. } = [hsx|
        <h1>Posts</h1>
        <ul>
            {forEach posts renderPost}
        </ul>
    |]
        where
            renderPost post = [hsx|<li>{get #title post}</li>|]

Inside the hsx quasi-quoter IHP interprets curly-brace interpolation as Haskell values safely. That only works inside the IHP DSL, not in ordinary Haskell files.

When IHP fits

  • Solo side projects — Rails-like CRUD speed.
  • Small-team SaaS back office — migrations, auth, admin views built in.
  • Haskell on-ramp — you can ship a working web app without confronting monad transformers head-on.

7. Servant — typed HTTP API

Where IHP is full-stack, Servant is an API-only library. One central idea: describe the API at the type level.

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

module Api where

import Data.Aeson (FromJSON, ToJSON)
import GHC.Generics (Generic)
import Servant

data User = User
  { userId   :: Int
  , userName :: String
  } deriving (Generic)

instance ToJSON User
instance FromJSON User

-- The API as a type
type UserAPI =
       "users" :> Get '[JSON] [User]
  :<|> "users" :> Capture "id" Int :> Get '[JSON] User
  :<|> "users" :> ReqBody '[JSON] User :> Post '[JSON] User

-- Handlers for that type
userAPI :: Server UserAPI
userAPI = listUsers :<|> getUser :<|> createUser
  where
    listUsers     = pure [User 1 "alice", User 2 "bob"]
    getUser uid   = pure (User uid "alice")
    createUser u  = pure u

The magic of this code is that UserAPI — the type — is the source of truth.

  • Wrong handlers fail to compile. A route declared as Get '[JSON] [User] that returns Int will be rejected.
  • The client — via servant-client — is generated from the same type.
  • The OpenAPI / Swagger doc — via servant-openapi3 — is generated from the same type.

Servant + warp server

import Network.Wai.Handler.Warp (run)
import Servant

main :: IO ()
main = do
  putStrLn "Listening on http://localhost:8081"
  run 8081 (serve (Proxy :: Proxy UserAPI) userAPI)

Who uses Servant

  • Hasura GraphQL Engine internal services
  • Channable, Mercury Bank, Wire
  • Many OSS backends

API changes that turn into compile errors are the core value.


8. Yesod / Snap / Scotty / Spock — other web frameworks

Yesod (Michael Snoyman)

yesodweb.com — by Michael Snoyman, the creator of Stack and Stackage. Older than IHP, famous for heavy type use including type-safe URLs and type-safe widgets.

-- Foundation.hs (Yesod routing snippet)
mkYesodData "App" [parseRoutes|
/                HomeR   GET
/posts           PostsR  GET POST
/posts/#PostId   PostR   GET DELETE
|]

Snap

snapframework.com — academically rooted framework. Known for Snaplets module composition. Less active development, still around in existing projects.

Scotty

hackage.haskell.org/package/scotty — a Sinatra-style microframework. Great for spinning up something short and lightweight.

{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty

main :: IO ()
main = scotty 3000 $ do
  get "/" $ text "hello scotty"
  get "/hello/:name" $ do
    n <- captureParam "name"
    text ("hello, " <> n)

Spock

A Scotty-class microframework that bundles session, CSRF, and DB pooling as built-in middleware.

Which one

  • Typed API focus: Servant.
  • Full-stack with migrations: IHP.
  • Full-stack with heavy types: Yesod.
  • Microservice / sidecar: Scotty.
  • Micro plus session and auth: Spock.

9. Effect systems — Effectful / Polysemy / fused-effects / Bluefin

The strength and the entry barrier of Haskell are its effect systems. Side effects — IO, state, exceptions, logging, DB access — are tracked by types.

The classic was the mtl style: stack monad transformers (StateT, ReaderT, ExceptT). Powerful but error messages get long and the performance trade-off is real.

In 2026, Effectful is effectively the new default.

Effectful

hackage.haskell.org/package/effectful — simpler model than Polysemy / fused-effects, compiler-friendly performance, mtl-like ergonomics.

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE GADTs #-}

import Effectful
import Effectful.Reader.Static (Reader, ask, runReader)
import Effectful.Error.Static (Error, throwError, runError)

-- Explicit effects: Reader + Error
loadUser :: (Reader String :> es, Error String :> es) => Int -> Eff es String
loadUser uid = do
  prefix <- ask
  if uid > 0
    then pure (prefix ++ ": user-" ++ show uid)
    else throwError "invalid uid"

main :: IO ()
main = do
  result <- runEff
          . runError @String
          . runReader "PREFIX"
          $ loadUser 42
  print result   -- Right "PREFIX: user-42"

Polysemy

hackage.haskell.org/package/polysemy — academic free-monad + free-algebra approach. Strong reinterpretation power, heavier types.

fused-effects

hackage.haskell.org/package/fused-effects — carrier-based effects. The compiler fuses effect composition at compile time for performance.

Bluefin

hackage.haskell.org/package/bluefin — a new entrant in 2024-25. Focused on scoped effects and delimited continuations as first class. Uses new RTS facilities in GHC 9.10.

-- Bluefin-style (conceptual example)
import Bluefin.Eff
import Bluefin.State

bumpCounter :: e :> es => State Int e -> Eff es Int
bumpCounter ref = do
  modify ref (+ 1)
  get ref

Which to use

  • New code, mtl feel: Effectful.
  • Research / education / strong expressiveness: Polysemy.
  • Perf-sensitive, fixed call graph: fused-effects.
  • Like the new and shiny, scoped effects: Bluefin.

10. ORM — Persistent / Beam / Esqueleto

Persistent (the Yesod camp)

Michael Snoyman's persistent — write your model in a DSL, the compiler turns it into data types and migrations. Supports SQL and some NoSQL backends.

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}

import Database.Persist.TH

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Post
    title Text
    body  Text
    deriving Show
User
    name  Text
    posts [PostId]
    deriving Show
|]

Beam

haskell-beam.github.io — generic-based, more type-safe SQL. Closer to SQL than Persistent, with Postgres / MySQL / SQLite backends.

Esqueleto

Sits on top of Persistent and exposes type-safe JOINs and subqueries as an EDSL.

import qualified Database.Esqueleto.Experimental as E

-- Post count per user
usersWithPostCount = E.select $ do
  (u E.:& p) <- E.from $ E.table @User
       `E.leftJoin` E.table @Post
       `E.on` (\(u E.:& p) -> E.just (u E.^. UserId) E.==. p E.?. PostUserId)
  E.groupBy (u E.^. UserId)
  pure (u, E.count (p E.?. PostId))

Which one

  • Quick CRUD: Persistent.
  • JOIN-heavy analytics queries: Esqueleto on top of Persistent.
  • Closer to SQL, larger domain: Beam.

11. Megaparsec — parser combinators

hackage.haskell.org/package/megaparsec — the 2026 default parser combinator library. Successor to Parsec; unlike Attoparsec, the core value is human-readable error messages.

{-# LANGUAGE OverloadedStrings #-}
import Data.Void (Void)
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
import Data.Text (Text)

type Parser = Parsec Void Text

data JsonValue
  = JNull
  | JBool Bool
  | JNumber Double
  | JString Text
  | JArray  [JsonValue]
  deriving Show

sc :: Parser ()
sc = L.space space1 (L.skipLineComment "//") empty

lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc

jsonNull :: Parser JsonValue
jsonNull = JNull <$ lexeme (string "null")

jsonBool :: Parser JsonValue
jsonBool = JBool True  <$ lexeme (string "true")
       <|> JBool False <$ lexeme (string "false")

jsonNumber :: Parser JsonValue
jsonNumber = JNumber <$> lexeme L.signed L.float

jsonValue :: Parser JsonValue
jsonValue = choice [jsonNull, jsonBool, jsonNumber]

Megaparsec strengths:

  • Automatic position tracking — errors show line and column.
  • Custom errorscustomFailure adds domain-specific failures.
  • Backtracking control — explicit via try.

Pandoc itself uses Megaparsec and earlier Parsec extensively internally.


12. Aeson — JSON

hackage.haskell.org/package/aeson — the de facto Haskell JSON library. The 2.2 major line is stable in 2026.

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

import Data.Aeson
import GHC.Generics

data Post = Post
  { postId    :: Int
  , postTitle :: String
  } deriving (Show, Generic)

instance ToJSON Post where
  toEncoding = genericToEncoding defaultOptions
instance FromJSON Post

main :: IO ()
main = do
  let p  = Post 1 "Hello"
      bs = encode p
  print bs
  print (decode bs :: Maybe Post)

Aeson 2 highlights

  • KeyMap — object keys moved from Text to Key, improving collision and hash safety.
  • Generic defaults are fast enough — Template Haskell macros are usually not needed.
  • Custom OptionsfieldLabelModifier makes snake_case and camelCase translation natural.
options :: Options
options = defaultOptions
  { fieldLabelModifier = camelTo2 '_'   -- postId -> post_id
  , omitNothingFields  = True
  }

13. Testing — hedgehog / tasty / hspec

The Haskell testing ecosystem rests on three pillars.

hspec (BDD)

import Test.Hspec

main :: IO ()
main = hspec $ do
  describe "sum" $ do
    it "sums an empty list to 0" $
      sum ([] :: [Int]) `shouldBe` 0
    it "sums [1,2,3] to 6" $
      sum [1, 2, 3 :: Int] `shouldBe` 6

tasty (test runner)

A runner that ties many test libraries into one tree: tasty-hspec, tasty-hedgehog, tasty-hunit, and more.

import Test.Tasty
import Test.Tasty.HUnit

main :: IO ()
main = defaultMain $ testGroup "all"
  [ testCase "trivial" $ (1 + 1) @?= (2 :: Int)
  ]

hedgehog (property testing)

QuickCheck's successor. Its standout feature is integrated shrinking — failing cases automatically shrink to a minimal counter-example.

import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range

prop_reverse_involutive :: Property
prop_reverse_involutive = property $ do
  xs <- forAll $ Gen.list (Range.linear 0 100) (Gen.int Range.linearBounded)
  reverse (reverse xs) === xs

Why property tests matter: instead of "five cases" you assert "this invariant holds across thousands of random inputs". When it fails, hedgehog auto-shrinks to a tiny readable counter-example.

Pick guide

  • BDD unit tests: hspec.
  • Runner integration: tasty.
  • Properties with auto-shrinking: hedgehog.

14. Liquid Haskell — refinement types

ucsd-progsys.github.io/liquidhaskell-blog/ — a formal verification tool that layers refinement types on top of ordinary Haskell.

The core idea: write a predicate beside the type, and an SMT solver (Z3 and friends) proves the predicate always holds at compile time.

{-@ measure llen @-}
llen :: [a] -> Int
llen []     = 0
llen (_:xs) = 1 + llen xs

{-@ head :: { xs:[a] | llen xs > 0 } -> a @-}
head :: [a] -> a
head (x:_) = x
head []    = error "won't happen"   -- LH proves this line is unreachable

LH lets you encode "this function cannot be called with an empty list" as part of the type, and the compiler rejects callers that fail to satisfy that condition.

Used in academia and parts of industry (blockchain, aviation and automotive safety).


15. Hasktorch — machine learning

hasktorch.org — Haskell bindings to PyTorch's libtorch. Actively developed at Tweag and by HaskellML.

{-# LANGUAGE DataKinds #-}
import Torch

main :: IO ()
main = do
  x <- randn' [2, 3]     -- Tensor [2, 3]
  y <- randn' [3, 4]
  let z = matmul x y
  print z

What makes Hasktorch attractive is encoding tensor shapes in types.

import Torch.Typed

-- Matrix multiplication whose shapes are checked at compile time
matmul' :: Tensor '[2, 3] Float -> Tensor '[3, 4] Float -> Tensor '[2, 4] Float
matmul' = matmul

If you try to multiply incompatible shapes, GHC refuses. The classic PyTorch shape mismatch becomes a compile-time error.


16. Pandoc — John MacFarlane

pandoc.org — UC Berkeley philosophy professor John MacFarlane has maintained the universal document converter since 2006. Around 40 input formats and 60 output formats. It travels freely between Markdown, LaTeX, DOCX, HTML, ePub, PDF, MediaWiki, RST, and more.

# Markdown -> PDF
pandoc README.md -o readme.pdf

# Markdown -> DOCX with citations
pandoc paper.md --citeproc --bibliography refs.bib -o paper.docx

# HTML -> EPUB
pandoc book.html -o book.epub --metadata title="My Book"

Pandoc's internals are elegant too.

  • PandocAST — every input format normalizes into this AST.
  • Readers — per-format parsers (Markdown reader, LaTeX reader, ...).
  • Writers — per-format serializers (HTML writer, PDF via LaTeX, ...).
  • Filters — transform the AST in Lua or Haskell.

It is the most visible "end users use this every day" project in the Haskell ecosystem.


17. Cardano — Charles Hoskinson and IOG

cardano.org — the blockchain platform built by Ethereum co-founder Charles Hoskinson after leaving the Ethereum project. Run by IOG (Input Output Global, formerly IOHK). The node is entirely Haskell, and smart contracts are written in Plutus (a Haskell DSL).

Why Haskell:

  • Formal verification — finance demands mathematical proof that code meets spec.
  • Purity — consensus must be deterministic; isolated IO in Haskell fits naturally.
  • Type system — guarantees verified changes.

Cardano core consists of:

  • cardano-node — node daemon, Haskell.
  • cardano-ledger — ledger rules, implemented directly from the Haskell specification.
  • plutus-core — smart contract core language.
  • Plutus Tx — the subset of Haskell that compiles to Plutus.
-- Plutus Tx (conceptual example)
{-# INLINABLE mkValidator #-}
mkValidator :: () -> Integer -> ScriptContext -> Bool
mkValidator _ guess _ = guess == 42

This validator runs on-chain to verify transactions. Plutus compiles a Haskell subset to its own core (Plutus Core), which the node evaluates.


18. Korea / Japan — Haskell Korea, ja-haskell, IOHK Japan

Korea

  • Haskell Korea (Facebook group, Discord) — community since the mid-2010s. Irregular quarterly meetups.
  • Publications: translations such as "Haskell Programming from First Principles" and locally authored "Programming Haskell" style books.
  • Universities: KAIST, Seoul National University, POSTECH PL groups use Haskell in teaching and research.
  • Industry use is limited, but some fintech and security teams have adopted it.

Japan

  • ja-haskell — Japanese Haskell community on Slack and X. Active weekly.
  • Haskell Day, irregular Haskell Symposium Japan — presentation events.
  • Books: Kazu Yamamoto (IIJ Lab) translates and writes; many other titles.
  • IOHK Japan — Cardano IOG's Japan office in Tokyo is one of the most active Haskell-hiring places globally.
  • Industry: Tsuru Capital, HERP, Drivemode (acquired by Honda) use Haskell.

Beyond the English communities (r/haskell, Haskell Discourse, Discord), reading both regional communities makes the on-ramp smoother.


19. Who should learn Haskell

Two clear recommendations.

1. To learn functional programming head-on

Writing FP in JavaScript / Kotlin / Scala / OCaml is one thing. Writing it in an environment where purity and laziness are default is another. Haskell leaves no escape hatch. Every side effect shows up in types. That feels restrictive at first, but once it clicks the mental model carries to every other language you write later.

2. Domains where verification and DSLs are high-value

  • Finance (derivatives pricing, settlement)
  • Blockchain smart contracts
  • Compilers and language tooling (Pandoc, ShellCheck, Idris, dhall are all Haskell)
  • Aviation, automotive, medical with formal verification needs
  • Insurance and tax with complex domain rules

When Haskell is the wrong choice

  • Large team and you are the only Haskeller — hiring and onboarding cost is high.
  • Very short MVPs with weak library coverage.
  • Systems and embedded programming — Rust fits better.

20. References

  • GHC 9.10 release notes — downloads.haskell.org/ghc/9.10.1/docs/users_guide/9.10.1-notes.html
  • GHC 9.12 release notes — downloads.haskell.org/ghc/9.12.1/docs/users_guide/9.12.1-notes.html
  • GHCup — www.haskell.org/ghcup/
  • Cabal — cabal.readthedocs.io
  • Stack — docs.haskellstack.org
  • Stackage — www.stackage.org
  • Hackage — hackage.haskell.org
  • IHP — ihp.digitallyinduced.com
  • Servant — docs.servant.dev
  • Yesod — www.yesodweb.com
  • Snap — snapframework.com
  • Scotty — hackage.haskell.org/package/scotty
  • Effectful — hackage.haskell.org/package/effectful
  • Polysemy — hackage.haskell.org/package/polysemy
  • fused-effects — hackage.haskell.org/package/fused-effects
  • Bluefin — hackage.haskell.org/package/bluefin
  • Persistent — hackage.haskell.org/package/persistent
  • Beam — haskell-beam.github.io
  • Esqueleto — hackage.haskell.org/package/esqueleto
  • Megaparsec — hackage.haskell.org/package/megaparsec
  • Aeson — hackage.haskell.org/package/aeson
  • hedgehog — hedgehog.qa
  • tasty — hackage.haskell.org/package/tasty
  • hspec — hspec.github.io
  • Liquid Haskell — ucsd-progsys.github.io/liquidhaskell-blog/
  • Hasktorch — hasktorch.org
  • Pandoc — pandoc.org
  • Cardano — cardano.org
  • IOG — iohk.io
  • Haskell Foundation — haskell.foundation
  • Haskell Korea — Facebook group / Discord
  • ja-haskell — haskell.jp