-- | -- Module : Test.Speculate.Misc -- Copyright : (c) 2016-2017 Rudy Matela -- License : 3-Clause BSD (see the file LICENSE) -- Maintainer : Rudy Matela -- -- This module is part o Speculate. -- -- Miscellaneous functions I still did not find a reasonable place to put -- them in. module Test.Speculate.Misc ( functions1 , functions2 , functions3 , functions4 , fillings , expressionsOf , valuedExpressionsOf ) where import Test.Speculate import Test.Speculate.Expr import Test.Speculate.Utils import Data.Dynamic import Test.LeanCheck functions1 :: (Typeable a, Typeable b) => Expr -> [(Expr,a->b)] functions1 e = case l undefined of [] -> [] _ -> fist l where l = \x -> [(e',v) | e' <- fillings e [constant "x" x], let Just v = evaluate e'] functions2 :: (Typeable a, Typeable b, Typeable c) => Expr -> [(Expr,a->b->c)] functions2 e = case l undefined undefined of [] -> [] _ -> fist2 l where l = \x y -> [(e',v) | e' <- fillings e [constant "x" x, constant "y" y] , let Just v = evaluate e'] functions3 :: (Typeable a, Typeable b, Typeable c, Typeable d) => Expr -> [(Expr,a->b->c->d)] functions3 e = case l undefined undefined undefined of [] -> [] _ -> fist3 l where l = \x y z -> [(e',v) | e' <- fillings e [constant "x" x, constant "y" y, constant "z" z] , let Just v = evaluate e'] functions4 :: (Typeable a, Typeable b, Typeable c, Typeable d, Typeable e) => Expr -> [(Expr,a->b->c->d->e)] functions4 e = case l undefined undefined undefined undefined of [] -> [] _ -> fist4 l where l = \x y z w -> [(e',v) | e' <- fillings e [constant "x" x, constant "y" y, constant "z" z, constant "w" w] , let Just v = evaluate e'] -- This function is dangerous: -- -- @f@ should always return the same number of values -- and should not evaluateuate it's argument when producing the list spine -- -- fist (function-list), in lack of a better name fist :: (a->[(z,b)]) -> [(z,a->b)] fist f = [ (fst $ f' undefined, snd . f') | i <- [0..(length (f undefined)-1)] , let f' = (!! i) . f ] fist2 :: (a->b->[(z,c)]) -> [(z,a->b->c)] fist2 f = map (id *** curry) $ fist (uncurry f) fist3 :: (a->b->c->[(z,d)]) -> [(z,a->b->c->d)] fist3 f = map (id *** curry3) $ fist (uncurry3 f) fist4 :: (a->b->c->d->[(z,e)]) -> [(z,a->b->c->d->e)] fist4 f = map (id *** curry4) $ fist (uncurry4 f) -- All possible fillings of holes in an expression: -- -- * For an expression without holes, this returns a singleton list with that -- expression. -- -- * If there is no type match between the given filler-expressions, -- return an empty list. fillings :: Expr -> [Expr] -> [Expr] fillings e vs = [fill e f | f <- fs] where fs = productsList [[v | v <- vs, typ v == h] | h <- holes e] -- | Given a list of atomic expressions, enumerate experssions by application -- -- NOTE: for now, very inneficient -- -- This function exists solely for documentation and will never actually be -- useful, as: -- -- > mapT fst $ classes -- -- Will return as expressions that are semantially different (and is more -- efficient) -- -- Eventually this function will be removed from Speculate expressionsOf :: [Expr] -> [[Expr]] expressionsOf ds = [ds] \/ productMaybeWith ($$) es es `addWeight` 1 where es = expressionsOf ds -- | Given a list of atomic expressinos, enumerated expressions of a given type -- by application. -- -- Never will be actually useful, see 'expressionsOf'. -- -- Eventually this functino will be removed from Speculate valuedExpressionsOf :: Typeable a => [Expr] -> [[(Expr,a)]] valuedExpressionsOf = mapTMaybe exprValue . expressionsOf where exprValue :: Typeable a => Expr -> Maybe (Expr,a) exprValue e = (,) e `fmap` evaluate e