-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Branch on whether a constraint is satisfied -- -- This library provides a mechanism that can be used to branch on -- whether a constraint is satisfied (not limited to typeclass -- instances). -- -- Usage example: -- --
--   {-# OPTIONS_GHC -fplugin=IfSat.Plugin #-}
--   
--   module MyModule where
--   
--   import Data.Constraint.If ( IfSat(ifSat) )
--   
--   hypot :: forall a. ( Floating a, IfSat (FMA a) ) => a -> a -> a
--   hypot = ifSat @(FMA a) withFMA withoutFMA
--     where
--       withFMA :: FMA a => a -> a -> a
--       withFMA x y =
--         let
--           h = sqrt $ fma x x (y * y)
--           h² = h * h
--           x² = x * x
--           u = fma (-y) y (h² - x²) + fma h h (-h²) - fma x x (-x²)
--         in
--           h - u / ( 2 * h )
--       withoutFMA :: a -> a -> a
--       withoutFMA x y = sqrt ( x * x + y * y )
--   
-- -- 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 \ x y z -> ( x * y ) + z in a single -- instruction, providing stronger guarantees about precision of the -- result. -- -- 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. @package if-instance @version 0.3.0.0 -- | This module defines the constraint disjunction typeclass ||, -- with method dispatch: -- --
--   dispatch :: ( c || d ) => ( c => r ) -> ( d => r ) -> r
--   
-- -- An expression of the form dispatch @c @d yes no denotes a -- selection between the two branches yes and no: -- -- -- -- If you don't need additional constraints in the fallback branch, you -- can also use: -- --
--   ifSat :: IfSat c => ( c => r ) -> r -> r
--   
-- -- This is the special case of dispatch which taes d to -- be the trivial constraint, d ~ ( () :: Constraint). -- -- This module also provides the type family IsSat :: -- Constraint -> Bool, which, when reduced, will check whether -- the constraint provided as an argument is satisfied. -- -- To use this functionality, you must enable the corresponding -- plugin, by adding {-# OPTIONS_GHC -fplugin=IfSat.Plugin -- #-} to the header of your module. -- --

Example

-- -- We can select the more efficient nubOrd function when an -- Ord instance is available: -- --
--   myNub :: forall (a :: Type). ( Eq a, IfSat (Ord a) ) => [a] -> [a]
--   myNub = ifSat @(Ord a) nubOrd nub
--    -- 'nubOrd' when 'Ord a' is satisfied, 'nub' otherwise.
--   
-- -- When a user calls myNub, e.g.: -- --
--   foo :: [(Int, Int)]
--   foo = myNub [(1,2), (3,3), (1,2), (2,2), (1,2), (1,4)]
--   
-- -- GHC will discharge the IfSat (Ord (Int,Int)) constraint by -- trying to solve the Ord (Int, Int) constraint. In this case, -- GHC can solve the constraint using the two top-level instances (which -- we assume are in scope): -- --
--   instance Ord Int
--   instance (Ord a, Ord b) => Ord (a,b)
--   
-- -- As the Ord (Int,Int) can be solved, GHC thus choose the -- first branch in ifSat, which in this case is nubOrd. -- --

When does branch selection occur?

-- -- What is important to understand is that the branch selection happens -- precisely when the IfSat ct constraint is solved. -- --
--   { -# OPTIONS_GHC -fplugin=IfSat.Plugin #- }
--   module M1 where
--   
--   showFun :: forall (a :: Type). IfSat ( Show ( a -> a ) ) => ( a -> a ) -> String
--   showFun = ifSat @( Show (a -> a) ) show ( \ _ -> "<<function>>" )
--   
--   test1 :: ( Bool -> Bool ) -> String
--   test1 fun = showFun fun
--   
--   ----------------------------------------
--   
--   { -# OPTIONS_GHC -fplugin=IfSat.Plugin #- }
--   module M2 where
--   
--   import M1
--   
--   instance Show ( Bool -> Bool ) where
--     show f = show [ f False, f True ]
--   
--   test2 :: ( a -> a ) -> String
--   test2 fun = showFun fun
--   
--   test3 :: ( Bool -> Bool ) -> String
--   test3 fun = showFun fun
--   
-- -- After loading M2, we get the following results: -- --
--   >>> test1 not
--   "<<function>>"
--   
-- -- In this example, to typecheck test1 we need to solve -- IfSat (Show (Bool -> Bool)) inside module M1. As -- no instance for Show (Bool -> Bool) is available in -- M1, we pick the second branch, resulting in -- "<<function>>". -- --
--   >>> test2 not
--   "<<function>>"
--   
-- -- In this example, we must solve IfSat (Show (a -> a)) -- within M2. There is no such instance in M2, so we -- pick the second branch. It doesn't matter that we are calling -- test2 with a function of type Bool -> Bool: we -- had to solve IfSat (Show (a -> a)) when type-checking the -- type signature of test2. -- --
--   >>> test3 not
--   "[True, False]"
--   
-- -- In this last example, we must solve IfSat (Show (Bool -> -- Bool)), but as we're in M2, such an instance is -- available, so we choose the first branch. -- -- Note in particular that test1 and test3 have the -- exact same definition (same type signature, same body), but produce a -- different result. This is because the satisfiability check happens in -- different contexts. module Data.Constraint.If class c || d -- | dispatch @c @d a b returns a if the constraint -- c is satisfied, otherwise b. -- --
--   dispatch :: ( c || d ) => ( c => r ) -> ( d => r ) -> r
--   
-- -- Requires the if-instance plugin: add {-# OPTIONS_GHC -- -fplugin=IfSat.Plugin #-} to the header of your module. -- -- Note: the selection happens at the point in the code where the c -- || d constraint is solved. dispatch :: (||) c d => ((IsSat c ~ True, c) => r) -> ((IsSat c ~ False, IsSat d ~ True, d) => r) -> r type IfSat ct = (ct || ()) -- | ifSat @ct a b returns a if the constraint -- ct is satisfied, and b otherwise. -- -- Requires the if-instance plugin: add {-# OPTIONS_GHC -- -fplugin=IfSat.Plugin #-} to the header of your module. -- -- Note: the selection happens at the point in the code where the -- IfSat ct constraint is solved. ifSat :: forall ct r. IfSat ct => ((IsSat ct ~ True, ct) => r) -> (IsSat ct ~ False => r) -> r -- | IsSat ct returns True if ct is satisfied, -- and False otherwise. -- -- The satisfiability check occurs at the moment of performing -- type-family reduction. type family IsSat ct module IfSat.Plugin -- | A type-checking plugin that solves ct_l || ct_r constraints. -- This allows users to branch on whether ct_l is satisfied. -- -- To use this plugin, add {-# OPTIONS_GHC -fplugin=IfSat.Plugin -- #-} to your module header. -- -- A ct_l || ct_r instance is solved by trying to solve -- ct_l: -- -- -- -- This means that the branch selection occurs precisely at the moment at -- which we solve the ct_l || ct_r constraint. See the -- documentation of dispatch for more information. plugin :: Plugin