reflection-1.5.1.2: Reifies arbitrary terms into types that can be reflected back into terms
This package addresses the configuration problem which is
propogating configurations that are available at run-time, allowing
multible configurations to coexist without resorting to mutable
global variables or unsafePerformIO
.
An example is modular arithmetic where the modulus itself can be supplied at run-time:
foo :: Modular s => Modulus s foo = 1000 * 1000 * 5 + 2000
>>>
withModulus 1280 foo
1040
given the following setup:
{--} import Data.Proxy (Proxy(Proxy)) import Data.Reflection (Reifies, reflect, reify)
and definitions:
data Modulus s = M { getModulus :: Integer } type Modular s =Reifies
s Integer normalize :: forall s. Modular s => Integer -> Modulus s normalize n = M (mod n modulus) where modulus =reflect
(Proxy
::Proxy
s) instance Modular s => Num (Modulus s) where M a + M b = normalize (a + b) M a * M b = normalize (a * b) withModulus :: Integer -> (forall s. Modular s => Modulus s) -> Integer withModulus m v =reify
m (getModulus . asProxyOf v) where asProxyOf :: f s -> Proxy s -> f s asProxyOf = const
That package is an implementation of the ideas presented in the paper "Functional Pearl: Implicit Configurations" by Oleg Kiselyov and Chung-chieh Shan (original paper). However, the API has been streamlined to improve performance.
Austin Seipp's tutorial Reflecting values to types and back provides a summary of the approach taken by this library, along with more motivating examples.
Modules
- Data