MyNixOS website logo
Description

A compatibility layer and GHC plugin for withDict from "GHC.Magic.Dict".

ghc-magic-dict-compat - A compatibility layer and GHC Plugin for withDict magic function

Since GHC 9.4, the compiler provides magic type-class WithDict and its member function withDict:

withDict :: 
  forall cls meth {rr} (r :: Type rr).
  WithDict cls meth =>
  meth ->
  (cls => r) ->
  r

This is the much safer version of unsafeCoerce to (unsafely) produce an instance dictionary for singleton classes dynamically - the compiler checks the preconditions statically at the compile time. Although it is potentially unsafe, this combinator is particularly useful when one writes the library manipulating instance dictionary dynamically.

This package provides a thin compatibility layer for withDict from GHC.Magic.Dict for GHC <9.4. The package consists of the following two modules:

  • GHC.Magic.Dict.Compat
  • GHC.Magic.Dict.Plugin

All you have to do is to import GHC.Magic.Dict.Compat and put the following at the top of modules calling withDict:

{-# OPTIONS_GHC -fplugin GHC.Magic.Dict.Plugin #-}

GHC.Magic.Dict.Compat provides a type-class WithDict and withDict combinator for GHC <9.4; it just re-expose them for GHC >= 9.4. For GHC <9.4, user-facing API is almost the same, except for `withDict` is _not_ a member function of `WithDict`. This is to prevent user-defined instances of `WithDict` by imposing unsolvable default signatures for hidden member functions. Still, users can refer to `WithDict` the constraint and use `withDict` function almost the same way as in GHC >=9.4, so this subtle difference should not be a big problem.

As users cannot define the instance of WithDict manually, the GHC.Magic.Dict.Compat module alone is not enough. Here, the GHC Plugin GHC.Magic.Dict.Plugin comes into play. For GHC <9.4, the plugin generates the dictionary for `WithDict` dynamically at the compile time, employing the almost the same logic as GHC >= 9.4. For newer GHC, it does no-op.

Usage

  1. Import withDict (and WithDict if necessary) from GHC.Magic.Dict.Compat
  2. Enable GHC Plugin GHC.Magic.Dict.Plugin either by placing {-# GHC_OPTIONS -fplugin GHC.Magic.Dict.Plugin #-} at the top or adding -fplugin GHC.Magic.Dict.Plugin to ghc-options of the package.

With this, you can freely use withDict both with GHC <9.4 and >=9.4.

Example

{-# LANGUAGE RankNTypes, ScopedTypeVariables, TypeApplications, ConstraintKinds #-}
{-# GHC_OPTIONS -fplugin GHC.Magic.Dict.Plugin #-}
module MyModule where
import GHC.Magic.Dict.Compat

class Given a where
  given :: a

give :: a -> (Given a => r) -> r
give = withDict @(Given a) @a
Metadata

Version

0.0.0.0

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows