if-instance: Branch on whether a constraint is satisfied

[ bsd3, library, plugin, type-system ] [ Propose Tags ]

This library provides a mechanism that can be used to branch on whether a constraint is satisfied (not limited to typeclass instances, despite the name of the library).

Usage example:

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

module MyModule where

import Data.Constraint.If ( IfCt(ifCt) )

hypot :: forall a. ( Floating a, IfCt (FMA a) ) => a -> a -> a
hypot = ifCt @(FMA a) withFMA withoutFMA
where
withFMA :: FMA a => a -> a -> a
withFMA a b =
let
h = sqrt \$ fma a a (b * b)
h² = h * h
a² = a * a
x = fma (-b) b (h² - a²) + fma h h (-h²) - fma a a (-a²)
in
h - x / ( 2 * h )
withoutFMA :: a -> a -> a
withoutFMA a b = sqrt ( a * a + b * b )


Here we select between two ways of computing the hypotenuse function based on whether we have access to the fused multiply-add operation

 fma :: FMA a => a -> a -> a -> a

which computes  \ a b c -> ( a * b ) + c  in a single instruction, providing stronger guarantees about precision of the resul.

A call of the form hypot @MyNumberType will either use the robust withFMA function when an FMA MyNumberType instance is available, or will fallback to the simple withoutFMA implementation when no such instance can be found.

Modules

[Index] [Quick Jump]

• Data
• Constraint
• Data.Constraint.If
• IfCt
• IfCt.Plugin