Write plugins for magic type families with ease.
Please see the README on GitHub at https://github.com/isovector/type-sets/tree/master/magic-tyfams#readme
magic-tyfams
Dedication
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
Overview
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"
"Some.Module"
"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
Acknowledgments
Thanks to Christiaan Baaij and Matt Pickering for their indispensable help convincing GHC to do the right thing here.