magic-tyfams: Write plugins for magic type families with ease

[ bsd3, compiler-plugin, library ] [ Propose Tags ]

Please see the README on GitHub at

[Skip to Readme]
Versions [faq],,,
Change log
Dependencies base (>=4.7 && <5), ghc (>=8.6.3 && <8.8), ghc-tcplugins-extra (==0.3.*), syb (==0.7.*) [details]
License BSD-3-Clause
Copyright 2019 Sandy Maguire
Author Sandy Maguire
Category Compiler Plugin
Home page
Bug tracker
Source repo head: git clone
Uploaded by isovector at 2019-08-11T15:58:34Z
Distributions NixOS:
Downloads 1107 total (3 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs available [build log]
Last success reported on 2019-08-11 [all 1 reports]


[Index] [Quick Jump]


Maintainer's Corner

For package maintainers and hackage trustees

Readme for magic-tyfams-

[back to package description]




G.O.B.: Two drowned white doves from "Flowers to Doves," a rabbit from "Doves to Rabbit," also drowned. These were mice...

Tobias: From "Rabbit to Mice?"

G.O.B.: No. That can't be done. No, these were a part of something I call mice-cellaneous: "Mouse in Purse." "Mouse in Drink." Here's a mouse, now it's gone...

--Arrested Development


magic-tyfams writes the annoying parts of GHC plugins so you don't have to. It provides a convenient interface for implementing magical type families.

For example, consider the following definition in mypackage of an always-stuck type family:

module Some.Module where

type family CmpType (a :: k) (b :: k) :: Ordering

We can generate a plugin that will solve this:

module Some.Plugin where

plugin :: Plugin
plugin = magicTyFamPlugin "mypackage"
                          "CmpType" $
  withStuckSemantics $ \[_k, a, b] ->
    pure $ promoteOrdering $ nonDetCmpType a b

promoteOrdering :: Ordering -> Type
promoteOrdering = flip mkTyConApp [] . \case
   LT -> promotedLTDataCon
   EQ -> promotedEQDataCon
   GT -> promotedGTDataCon

Enabling this plugin via -fplugin=Some.Plugin will now automagically solve CmpType! Nice!

{-# OPTIONS_GHC -fplugin=Some.Plugin #-}

import Proxy

-- compiles just fine!
test :: Proxy (CmpType Int Int) -> Proxy 'EQ
test = id


Thanks to Christiaan Baaij and Matt Pickering for their indispensable help convincing GHC to do the right thing here.