Simon Peyton Jones
Microsoft Research
September 2015
Partial type signatures (Thomas Winant et al)
f :: _ -> Int -> [ _ ]
g :: (_) => a -> a
API annotations (Alan Zimmerman):
the ability to know exactly where every nonterminal in the original source text appears
Applicative as a superclass of Monad (finally)
More robust GMP hook-up (Herbert Valerio
Riedel)
Preliminary support for Cloud Haskell 'static'
Plugin API for a SMT solver in the type
inference engine (Iavor Diatchki,
experimental)
GADT-aware pattern-match
overlap/exhaustiveness warnings (George
Karachalias, Tom Schrjvers et al; see our ICFP
paper)
Injective type families (Jan Stolarek; see our
HS paper)
Applicative do-notation (Simon Marlow)
Implicit-parameter support for call stacks
(Eric Seidel et al)
Strict Haskell (Johan Tibbell and Adam
Sandberg Eriksson)
Overloaded record fields (Adam Gundry)
Kind equalities, and GADTs at the type level
(Richard Eisenberg and Stephanie Weirich)
Visible type application (Stephanie Weirich,
Richard Eisenberg)
Type-indexed type representations
MonadFail
DWARF-based stack backtraces (Peter
Wortmann)
A Shake-based build system (Andrey
Mokhov)
Backpack... (Edward Yang)
head :: [a] -> a
head (x:xs) = x
head []
= error "head of empty list"
ghci> complicated_function 89
*** Exception: head of empty list
But who called 'head'???????
head :: String -> [a] -> a
head _ (x:xs) = x
head info [] = error ("head of empty list" ++ info)
foogle x y z = ....(head "In foogle" ts)....
Change in head's type signature
Every call site must be changed to pass an
informative string
head :: (?cs :: CallStack) => [a] -> a
head (x:xs) = x
head []
= error ("head of empty list\n"
++ showCallStack ?cs)
foogle x y z = ....(head ts)....
ghci> complicated_function 89
*** Exception: Head of empty list
?cs, called at Foo.hs:8:60 in main:Foo
head, called at Foo.hs:10:9 in main:Foo
Better, but what if you don't know where
'foogle' was called?
head :: (?cs :: CallStack) => [a] -> a
head (x:xs) = x
head []
= error ("head of empty list\n"
++ showCallStack ?cs)
foogle :: (?cs :: CallStack) => Int -> Int
foogle x = ....(head e)....
Re-uses existing notation
Easy to implement: the constraint solver is
the only bit that changes
Zero impact on transformation, optimisation,
code generation, etc
Decent records are probably GHC's longestasked-for feature
It's a swamp: many designs, all with complex
tradeoffs.
We have finally plumped for a simple,
modular design, with three pieces:
1. Allow duplicate field labels
2. Record classes for overloading
3. Overloaded labels for convenience
data T = MkT { x, y :: Int }
data S = MkS { x :: Bool, z :: Int }
Record construction and pattern matching
are unaffected
f :: S -> T
f (MkS { x = v } = MkS { x = True, y = v }
Duplicated record selectors are ambiguous;
but NB selective import
module A where
import M( T(MkT, x, y) )
f r = x r + y r
-- But not S
class HasField (x :: Symbol) r where
type FieldType x r
getField :: Proxy# x -> r -> FieldType x r
Every field gives rise to a new instance
instance HasField "x" T where
type FieldType "x" T = Int
getField (MkT { x = v }) = v
Now selection is overloaded:
f :: T -> Int
f r = getField (Proxy :: Proxy "x") r + 1
-- Gets field "x" from a T record
class IsLabel (x :: Symbol) a where
fromLabel :: a
Syntax "#x" expands to (fromLabel @ "x" @t)
instance (HasField x r, a ~ FieldType x r)
=> IsLabel x (r -> a) where
fromLabel = getField (Proxy :: Proxy x)
So (#x r) would expand (via the instance) to
getField (Proxy :: Proxy "x")
just as we want
But the instance is library code; we can change it if
we want #x to mean a lens
class Typeable a where
typeRep :: Proxy a -> TypeRep
data Dynamic where
Dynamic :: TypeRep -> a -> Dynamic
toDyn :: forall a. Typeable a => a -> Dynamic
toDyn x = Dynamic trep x
where
trep :: TypeRep
trep = typeRep (Proxy :: Proxy a)
data Dynamic where
Dynamic :: TypeRep -> a -> Dynamic
fromDynamic :: forall a. Typeable a =>
Dynamic -> Maybe a
fromDynamic (Dynamic trx x)
| trx == trr = x
| otherwise = Nothing
where
trr = typeRep (Proxy :: Proxy a)
Does not typecheck because (trx == trr)
tells the type system nothing
data Dynamic where
Dynamic :: TypeRep -> a -> Dynamic
fromDynamic :: forall a. Typeable a =>
Dynamic -> Maybe a
fromDynamic (Dynamic trx x)
| trx == trr = unsafeCoerce x
| otherwise = Nothing
where
trr = typeRep (Proxy :: Proxy a)
And yet, comparing TypeReps should tell us
something! After all, they were built by the
compiler!
class Typeable a where
typeRep :: TypeRep a
eqT :: TypeRep a -> TypeRep b -> Maybe (a :~: b)
data a :~: b where
Refl :: a :~: a
Now, comparing TypeReps does tell us
something!
data Dynamic where
Dynamic :: TypeRep a -> a -> Dynamic
eqT :: TypeRep a -> TypeRep b -> Maybe (a :~: b)
fromDynamic :: forall a. Typeable a =>
Dynamic -> Maybe a
fromDynamic (Dynamic trx x)
= case eqT trx (typeRep :: TypeRep a) of
Just Refl -> Just x
Nothing
-> Nothing
From TypeRep to (TypeRep a) allows us to do
type-safe reflection
Useful for Cloud Haskell style applications
Smaller trusted code base. I think GHC
implementors only, rather than library
authors
Interestingly, it turns out to need Richard
Eisenberg's kind-level equalities!
GHC is flourishing
lots of users
lots of innovation
lots of contributors
Trac tickets over 10,000
GHC is more and more a community project,
both in leadership and execution
This is not a bad thing. But it relies on people
actually stepping up.
Introducing the new Well Typed GHC support team:
Austin Seipp
Ban Gamari
Major role
Not so much doing, but
enabling others to do
Bottom line
GHC and
(especially) its ecosystem
(cabal, Hackage, Haskell Platform...)
badly need your help
type system
optimisation
code generation for
many platforms
SIMD instructions
dynamic linking
GHCi
the GHC API
plugins
FFI
concurrency, STM
Cloud Haskell
the build system
packages
garbage collection,
finalisers
run-time system,
scheduling
profiling
....and more...
Profiling and debugging
Connection between profiler output and -ddump-simpl for autogenerated SCCs. Use DWARF annotations? (Norman)
Sample-based profiling. DWARF will give this. (Lennart)
Free stack traces: always on. DWARF will give this. (Johan)
Core-to-Core API is hard to use (tall guy, glasses,
black hair)
Inlining reporting (John Wigely)
Show instances for GHC internals (Johan)
Code generation something ...
© Copyright 2026 Paperzz