singletons-th
A framework for generating singleton types
http://www.github.com/goldfirere/singletons
| LTS Haskell 24.16: | 3.4 |
| Stackage Nightly 2025-10-24: | 3.5 |
| Latest on Hackage: | 3.5 |
singletons-th-3.5@sha256:db41d7bab9e14dcf949d4d0db115f68f0aeb64c8c93a39784f12c8463d9c0452,4707Module documentation for 3.5
singletons-th
singletons-th defines Template Haskell functionality that allows
promotion of term-level functions to type-level equivalents and
singling functions to dependently typed equivalents. This library was
originally presented in
Dependently Typed Programming with Singletons,
published at the Haskell Symposium, 2012. See also
the paper published at Haskell Symposium, 2014,
which describes how promotion works in greater detail.
singletons-th generates code that relies on bleeding-edge GHC language
extensions. As such, singletons-th only supports the latest major version
of GHC (currently GHC 9.12). For more information,
consult the singletons
README.
You may also be interested in the following related libraries:
- The
singletonslibrary is a small, foundational library that defines basic singleton-related types and definitions. - The
singletons-baselibrary usessingletons-thto define promoted and singled functions from thebaselibrary, including thePrelude.
Changes
Changelog for the singletons-th project
3.5 [2024.12.11]
-
Require building with GHC 9.12.
-
Require building with
th-desugar-1.18or later. Notably,th-desugar-1.18now desugars all lambda,case, and\caseexpressions to\casesexpressions, and the same principle applies to the code thatsingletons-thgenerates.Generally speaking, most code should continue to work after this change. Note that singled code might now generate
-Wunused-matcheswarnings where it didn’t before. For example, previous versions ofsingletons-thwould not warn that thexinmap (\x -> ())is unused after singling it, but thissingletons-thwill now generate an-Wunused-matcheswarning for the singled version ofx. -
Add support for promoting and singling type variables that scope over the bodies of class method defaults and instance methods.
-
singletons-thcan now generate more precise types for singled data constructors whose parent data types have standalone kind signatures. For instance, consider this data type:$(singletons [d| type D :: forall k. k -> Type data D a = MkD |])Previously,
singletons-thwould generate the following type forSMkD(the singled counterpart toMkD):data SD :: forall k. k -> Type where SMkD :: forall a. SD (MkD :: D a)This was not as precise as it could have been, as the type of
SMkDdid not make the kind variablekeligible for visible type application (as is the case inMkD :: forall k (a :: k). D a).singletons-thnow accomplishes this by generating the following code instead:data SD :: forall k. k -> Type where SMkD :: forall k (a :: k). SD (MkD :: D a)
3.4 [2024.05.12]
- Require building with GHC 9.10.
- GHC 9.10 removes arity inference when kind-checking type families with
standalone kind signatures, persuant to this GHC
proposal.
In order to promote functions to type families with correct arities,
singletons-thusesTypeAbstractionsto bind type variable binders in the headers of promoted type families. As such, it is quite likely that you will need to enableTypeAbstractionsin order to make GHC accept code thatsingletons-thgenerates. - Fix a bug causing definitions with type signatures using inferred type
variable binders (e.g.,
forall a {b}. a -> b -> a) to fail to promote.
3.3 [2023.10.13]
-
Require building with GHC 9.8.
-
Singled data types with derived
EqorOrdinstances now generateEqorOrdinstances for the singleton type itself, e.g.,instance Eq (SExample a) where _ == _ = True instance Ord (SExample a) where compare _ _ = EQ -
singletons-thnow makes an effort to promote definitions that use scoped type variables. See the “Scoped type variables” section of theREADMEfor more information about whatsingletons-thcan (and can’t) do. -
singletons-thnow supports singling type-level definitions that useTypeAbstractions. -
Fix a bug in which data types using visible dependent quantification would generate ill-scoped code when singled.
-
Fix a bug in which singling a local variable that shadows a top-level definition would fail to typecheck in some circumstances.
-
Fix a bug in which
singletons-thwould incorrectly promote/single records to top-level field selectors whenNoFieldSelectorswas active.
3.2 [2023.03.12]
- Require building with GHC 9.6.
- Derived
POrdandSOrdinstances (arising from a use ofderiving Ord) now use(<>) @Orderingin their implementations instead of the customthenCmp :: Ordering -> Ordering -> Orderingfunction. While most code will likely continue to work after this change, this may break code that attempts to prove properties about the implementation of a derivedPOrd/SOrdinstance. - Fix a bug in which the
singDecideInstancesandshowSingInstances, as well asderiving Showdeclarations, would not respect custompromotedDataTypeOrConNameoptions. - Allow building with
mtl-2.3.*.
3.1.1 [2022.08.23]
- Require building with GHC 9.4.
- Improve error messages when attempting to promote a partial application of
a function arrow
(->), which is not currently supported.
3.1 [2021.10.30]
- Require building with GHC 9.2.
- Allow promoting and singling type applications in data constructor patterns.
- Make the Template Haskell machinery generate
SingI1andSingI2instances when possible. - Make
genDefunSymbolsand related functions less likely to trigger GHC#19743.
3.0 [2021.03.12]
-
The
singletonslibrary has been split into three libraries:- The new
singletonslibrary is now a minimal library that only providesData.Singletons,Data.Singletons.Decide,Data.Singletons.Sigma, andData.Singletons.ShowSing(if compiled with GHC 8.6 or later).singletonsnow supports building GHCs back to GHC 8.0, as well as GHCJS. - The
singletons-thlibrary defines Template Haskell functionality for promoting and singling term-level definitions, but but nothing else. This library continues to require the latest stable release of GHC. - The
singletons-baselibrary defines promoted and singled versions of definitions from thebaselibrary, including thePrelude. This library continues to require the latest stable release of GHC.
Consult the changelogs for
singletonsandsingletons-basefor changes specific to those libraries. For more information on this split, see the relevant GitHub discussion. - The new
-
Require building with GHC 9.0.
-
Data.Singletons.CustomStarandData.Singletons.SuppressUnusedWarningshave been renamed toData.Singletons.TH.CustomStarandData.Singletons.SuppressUnusedWarnings, respectively, to give every module insingletons-tha consistent module prefix. -
Due to the
singletonspackage split, thesingletons-thmodulesData.Singletons.THandData.Singletons.TH.CustomStar(formerly known asData.Singletons.CustomStar) no longer re-export any definitions from thesingletons-basemodulePrelude.Singletons(formerly known asData.Singletons.Prelude). Thesingletons-baselibrary now provides versions of these modules—Data.Singletons.Base.CustomStarandData.Singletons.Base.TH, respectively—that do re-export definitions fromPrelude.Singletons. -
“Fully saturated” defunctionalization symbols (e.g.,
IdSym1) are now defined as type families instead of type synonyms. This has two notable benefits:- Fully saturated defunctionalization symbols can now be given standalone kind signatures, which ensures that the order of kind variables is the same as the user originally declared them.
- This fixes a minor regression in
singletons-2.7in which the quality of:kind!output in GHCi would become worse when using promoted type families generated by Template Haskell.
Under certain circumstances, this can be a breaking change:
-
Since more TH-generated promoted functions now have type families on their right-hand sides, some programs will now require
UndecidableInstanceswhere they didn’t before. -
Certain definitions that made use of overlapping patterns, such as
natMinusbelow, will no longer typecheck:$(singletons [d| data Nat = Z | S Nat natMinus :: Nat -> Nat -> Nat natMinus Z _ = Z natMinus (S a) (S b) = natMinus a b natMinus a Z = a |])This can be worked around by avoiding the use of overlapping patterns. In the case of
natMinus, this amounts to changing the third equation to match on its first argument:$(singletons [d| natMinus :: Nat -> Nat -> Nat natMinus Z _ = Z natMinus (S a) (S b) = natMinus a b natMinus a@(S _) Z = a |])
-
The specification for how
singletonsdeals with record selectors has been simplified. Previously,singletonswould try to avoid promoting so-called “naughty” selectors (those whose types mention existential type variables that do not appear in the constructor’s return type) to top-level functions. Determing if a selector is naughty is quite challenging in practice, as determining if a type variable is existential or not in the context of Template Haskell is difficult in the general case. As a result,singletonsnow adopts the dumb-but-predictable approach of always promoting record selectors to top-level functions, naughty or not.This means that attempting to promote code with a naughty record selector, like in the example below, will no longer work:
$(promote [d| data Some :: (Type -> Type) -> Type where MkSome :: { getSome :: f a } -> Some f -- getSome is naughty due to mentioning the type variable `a` |])Please open an issue if you find this restriction burdensome in practice.
-
The
singEqInstanceOnlyandsingEqInstancesOnlyfunctions, which generateSEq(but notPEq) instances, have been removed. There is not much point in keeping these functions around now thatPEqnow longer has a special default implementation. UsesingEqInstance{s}instead. -
The Template Haskell machinery will no longer promote
TypeReptoType, as this special case never worked properly in the first place. -
The Template Haskell machinery will now preserve strict fields in data types when generating their singled counterparts.
-
Introduce a new
promotedDataTypeOrConNameoption toData.Singletons.TH.Options. Overriding this option can be useful in situations where one wishes to promote types such asNat,Symbol, or data types built on top of them. See the “Arrows,Nat,Symbol, and literals” section of theREADMEfor more information. -
Define a
Quoteinstance forOptionsM. A notable benefit of this instance is that it avoids the need to explicitlyliftTH quotes intoOptionsM. Before, you would have to do this:import Control.Monad.Trans.Class (lift) withOptions defaultOptions $ singletons $ lift [d| data T = MkT |]But now, it suffices to simply do this:
withOptions defaultOptions $ singletons [d| data T = MkT |]