-- |
-- Module      : Test.FitSpec.Mutable
-- Copyright   : (c) 2015-2017 Rudy Matela
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : Rudy Matela <rudy@matela.com.br>
--
-- Enumeration of function mutations
module Test.FitSpec.Mutable
  ( Mutable (..)
  , mutiersEq
--, mutantsIntegral
  )
where

import Test.LeanCheck
import Data.List (intercalate, delete)
import Data.Maybe
import Test.LeanCheck.Error (errorToNothing)
import Data.Ratio (Ratio)
import Data.Word (Word)

-- | This typeclass is similar to 'Listable'.
--
-- A type is 'Mutable' when there exists a function that
-- is able to list mutations of a value.
-- Ideally: list all possible values without repetitions.
--
-- Instances are usually defined by a 'mutiers' function that
-- given a value, returns tiers of mutants of that value:
--   the first  tier contains the equivalent mutant, of size 0,
--   the second tier contains mutants of size 1,
--   the third  tier contains mutants of size 2,
--   and so on.
--
-- The equivalent mutant is the actual function without mutations.
--
-- The size of a mutant is given by the sum of:
--   the number of mutated points (relations) and
--   the sizes of mutated arguments and results.
--
-- To get only inequivalent mutants,
-- just take the 'tail' of either 'mutants' or 'mutiers':
--
-- > tail mutants
--
-- > tail mutiers
--
-- Given that the underlying 'Listable' enumeration has no repetitions,
-- parametric instances defined in this file will have no repeated mutants.
class Mutable a where
  mutiers :: a -> [[a]]
  mutants :: a -> [a]
  mutiers = (a -> [a]) -> [a] -> [[a]]
forall a b. (a -> b) -> [a] -> [b]
map (a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[]) ([a] -> [[a]]) -> (a -> [a]) -> a -> [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [a]
forall a. Mutable a => a -> [a]
mutants
  mutants = [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[a]] -> [a]) -> (a -> [[a]]) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [[a]]
forall a. Mutable a => a -> [[a]]
mutiers
  {-# MINIMAL mutants | mutiers #-}


-- *** *** Instances for (non-functional) data types *** ***

-- | Implementation of 'mutiers' for non-functional data types.
-- Use this to create instances for user-defined data types, e.g.:
--
-- > instance MyData
-- >   where mutiers = mutiersEq
--
-- and for parametric datatypes:
--
-- > instance (Eq a, Eq b) => MyDt a b
-- >   where mutiers = mutiersEq
--
-- Examples:
--
-- > mutiersEq True = [[True], [False]]
-- > mutiersEq 2   = [[2], [0], [1], [], [3], [4], [5], [6], [7], [8], [9], ...]
-- > mutiersEq [1] = [[[1]], [[]], [[0]], [[0,0]], [[0,0,0],[0,1],[1,0],[-1]], ...]
mutiersEq :: (Listable a, Eq a) => a -> [[a]]
mutiersEq :: a -> [[a]]
mutiersEq a
x = [a
x] [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: a -> [[a]] -> [[a]]
forall a. Eq a => a -> [[a]] -> [[a]]
deleteT a
x [[a]]
forall a. Listable a => [[a]]
tiers

-- | > mutants () = [()]
instance Mutable ()   where mutiers :: () -> [[()]]
mutiers = () -> [[()]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

-- | > mutants 3 = [3,0,1,2,4,5,6,7,8,...]
instance Mutable Int  where mutiers :: Int -> [[Int]]
mutiers = Int -> [[Int]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

instance Mutable Integer where mutiers :: Integer -> [[Integer]]
mutiers = Integer -> [[Integer]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

instance Mutable Char where mutiers :: Char -> [[Char]]
mutiers = Char -> [[Char]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

-- | > mutants True = [True,False]
instance Mutable Bool where mutiers :: Bool -> [[Bool]]
mutiers = Bool -> [[Bool]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

-- | > mutants [0] = [ [0], [], [0,0], [1], ...
instance (Eq a, Listable a) => Mutable [a]       where mutiers :: [a] -> [[[a]]]
mutiers = [a] -> [[[a]]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

-- | > mutants (Just 0) = [Just 0, Nothing, ...
instance (Eq a, Listable a) => Mutable (Maybe a) where mutiers :: Maybe a -> [[Maybe a]]
mutiers = Maybe a -> [[Maybe a]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

instance (Eq a, Listable a, Eq b, Listable b) => Mutable (Either a b)
  where mutiers :: Either a b -> [[Either a b]]
mutiers = Either a b -> [[Either a b]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

instance (Eq a, Listable a, Integral a) => Mutable (Ratio a)
  where mutiers :: Ratio a -> [[Ratio a]]
mutiers = Ratio a -> [[Ratio a]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

instance Mutable Float    where mutiers :: Float -> [[Float]]
mutiers = Float -> [[Float]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq
instance Mutable Double   where mutiers :: Double -> [[Double]]
mutiers = Double -> [[Double]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq
instance Mutable Ordering where mutiers :: Ordering -> [[Ordering]]
mutiers = Ordering -> [[Ordering]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq
instance Mutable Word     where mutiers :: Word -> [[Word]]
mutiers = Word -> [[Word]]
forall a. (Listable a, Eq a) => a -> [[a]]
mutiersEq

{- Alternative implementations for Mutable Ints and Lists.
-- These do not improve results significantly.
-- That is why I have kept the simpler mutations above.

-- |- Generate mutants of an Integral value.
-- Alternates between successors and predecessors of the original number.
-- The enumeration starts "towards" zero.
mutantsIntegral :: Integral a => a -> [a]
mutantsIntegral i | i > 0     = [i..] +| tail [i,(i-1)..]
                  | otherwise = [i,(i-1)..] +| tail [i..]
-- NOTE: tail is there to avoid generating out of bound values
--       as (i-1) is usually safe while (i-2) is not.

instance Mutable Int  where mutants = mutantsIntegral

instance (Listable a, Mutable a) => Mutable [a]
  where mutiers []     = [ [] ]
                       : [ ]
                       : tail tiers
        mutiers (x:xs) = [ (x:xs) ]
                       : [ [] ]
                       : tail (lsProductWith (:) (mutiers x) (mutiers xs))
-- -}


-- *** *** Instances for functional types *** ***

-- | Mutate a function at a single point.
-- The following two declarations are equivalent:
--
-- > id' = id `mut` (0,1)
--
-- > id' 0 = 1
-- > id' x = x
mut :: Eq a => (a -> b) -> (a,b) -> (a -> b)
mut :: (a -> b) -> (a, b) -> a -> b
mut a -> b
f (a
x',b
fx') = \a
x -> if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x'
                         then b
fx'
                         else a -> b
f a
x

-- | Mutate a function at several points.
--
-- > f `mutate` [(x,a),(y,b),(z,c)] = f `mut` (x,a) `mut` (y,b) `mut` (z,c)
mutate :: Eq a => (a -> b) -> [(a,b)] -> (a -> b)
mutate :: (a -> b) -> [(a, b)] -> a -> b
mutate a -> b
f [(a, b)]
ms = ((a, b) -> (a -> b) -> a -> b) -> (a -> b) -> [(a, b)] -> a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (((a -> b) -> (a, b) -> a -> b) -> (a, b) -> (a -> b) -> a -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> b) -> (a, b) -> a -> b
forall a b. Eq a => (a -> b) -> (a, b) -> a -> b
mut) a -> b
f [(a, b)]
ms -- or: foldl mut f ms

-- | Return tiers of possible mutations for a single point of a function.
-- If the function is undefined at that point, no mutations are provided.
-- This function does not return the null mutant.
--
-- > (+1) `mutationsFor` 1 = [ [(1,0)], [(1,1)], [], [(1,3)], [(1,4)], ...
mutationsFor :: Mutable b => (a->b) -> a -> [[(a,b)]]
mutationsFor :: (a -> b) -> a -> [[(a, b)]]
mutationsFor a -> b
f a
x = case b -> Maybe b
forall a. a -> Maybe a
errorToNothing (a -> b
f a
x) of
                     Maybe b
Nothing -> []
                     Just b
fx -> ((,) a
x) (b -> (a, b)) -> [[b]] -> [[(a, b)]]
forall a b. (a -> b) -> [[a]] -> [[b]]
`mapT` [[b]] -> [[b]]
forall a. [a] -> [a]
tail (b -> [[b]]
forall a. Mutable a => a -> [[a]]
mutiers b
fx)

-- | Returns tiers of mutants on a selection of arguments of a function.
-- Will only return the null mutant from an empty selection of arguments.
tiersMutantsOn :: (Eq a, Mutable b) => (a->b) -> [a] -> [[a->b]]
tiersMutantsOn :: (a -> b) -> [a] -> [[a -> b]]
tiersMutantsOn a -> b
f [a]
xs = (a -> b) -> [(a, b)] -> a -> b
forall a b. Eq a => (a -> b) -> [(a, b)] -> a -> b
mutate a -> b
f ([(a, b)] -> a -> b) -> [[[(a, b)]]] -> [[a -> b]]
forall a b. (a -> b) -> [[a]] -> [[b]]
`mapT` [[[(a, b)]]] -> [[[(a, b)]]]
forall a. [[[a]]] -> [[[a]]]
products ((a -> [[(a, b)]]) -> [a] -> [[[(a, b)]]]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> a -> [[(a, b)]]
forall b a. Mutable b => (a -> b) -> a -> [[(a, b)]]
mutationsFor a -> b
f) [a]
xs)

-- |
-- > mutants not =
-- >   [ not
-- >   , \p -> case p of False -> False; _ -> not p
-- >   , \p -> case p of True  -> True;  _ -> not p
-- >   , \p -> case p of False -> False; True -> True
-- >   ]
instance (Eq a, Listable a, Mutable b) => Mutable (a -> b) where
  mutiers :: (a -> b) -> [[a -> b]]
mutiers a -> b
f = (a -> b) -> [a] -> [[a -> b]]
forall a b. (Eq a, Mutable b) => (a -> b) -> [a] -> [[a -> b]]
tiersMutantsOn a -> b
f ([a] -> [[a -> b]]) -> [[[a]]] -> [[a -> b]]
forall a b. (a -> [[b]]) -> [[a]] -> [[b]]
`concatMapT` [[a]] -> [[[a]]]
forall a. [[a]] -> [[[a]]]
setsOf [[a]]
forall a. Listable a => [[a]]
tiers


-- *** *** Instances for tuples *** ***

-- | > mutants (0,1) = [(0,1),(0,0),(1,1),(0,-1),...]
instance (Mutable a, Mutable b) => Mutable (a,b) where
  mutiers :: (a, b) -> [[(a, b)]]
mutiers (a
f,b
g) = a -> [[a]]
forall a. Mutable a => a -> [[a]]
mutiers a
f [[a]] -> [[b]] -> [[(a, b)]]
forall a b. [[a]] -> [[b]] -> [[(a, b)]]
>< b -> [[b]]
forall a. Mutable a => a -> [[a]]
mutiers b
g

instance (Mutable a, Mutable b, Mutable c) => Mutable (a,b,c) where
  mutiers :: (a, b, c) -> [[(a, b, c)]]
mutiers (a
f,b
g,c
h) = (a -> (b, c) -> (a, b, c)) -> [[a]] -> [[(b, c)]] -> [[(a, b, c)]]
forall a b c. (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
productWith (\a
f' (b
g',c
h') -> (a
f',b
g',c
h'))
                                (a -> [[a]]
forall a. Mutable a => a -> [[a]]
mutiers a
f) ((b, c) -> [[(b, c)]]
forall a. Mutable a => a -> [[a]]
mutiers (b
g,c
h))

instance (Mutable a, Mutable b, Mutable c, Mutable d)
      => Mutable (a,b,c,d) where
  mutiers :: (a, b, c, d) -> [[(a, b, c, d)]]
mutiers (a
f,b
g,c
h,d
i) = (a -> (b, c, d) -> (a, b, c, d))
-> [[a]] -> [[(b, c, d)]] -> [[(a, b, c, d)]]
forall a b c. (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
productWith (\a
f' (b
g',c
h',d
i') -> (a
f',b
g',c
h',d
i'))
                                  (a -> [[a]]
forall a. Mutable a => a -> [[a]]
mutiers a
f) ((b, c, d) -> [[(b, c, d)]]
forall a. Mutable a => a -> [[a]]
mutiers (b
g,c
h,d
i))

instance (Mutable a, Mutable b, Mutable c, Mutable d, Mutable e)
      => Mutable (a,b,c,d,e) where
  mutiers :: (a, b, c, d, e) -> [[(a, b, c, d, e)]]
mutiers (a
f,b
g,c
h,d
i,e
j) = (a -> (b, c, d, e) -> (a, b, c, d, e))
-> [[a]] -> [[(b, c, d, e)]] -> [[(a, b, c, d, e)]]
forall a b c. (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
productWith (\a
f' (b
g',c
h',d
i',e
j') -> (a
f',b
g',c
h',d
i',e
j'))
                                    (a -> [[a]]
forall a. Mutable a => a -> [[a]]
mutiers a
f) ((b, c, d, e) -> [[(b, c, d, e)]]
forall a. Mutable a => a -> [[a]]
mutiers (b
g,c
h,d
i,e
j))

instance (Mutable a, Mutable b, Mutable c, Mutable d, Mutable e, Mutable f)
      => Mutable (a,b,c,d,e,f) where
  mutiers :: (a, b, c, d, e, f) -> [[(a, b, c, d, e, f)]]
mutiers (a
f,b
g,c
h,d
i,e
j,f
k) = (a -> (b, c, d, e, f) -> (a, b, c, d, e, f))
-> [[a]] -> [[(b, c, d, e, f)]] -> [[(a, b, c, d, e, f)]]
forall a b c. (a -> b -> c) -> [[a]] -> [[b]] -> [[c]]
productWith (\a
f' (b
g',c
h',d
i',e
j',f
k') ->
                                           (a
f',b
g',c
h',d
i',e
j',f
k'))
                                      (a -> [[a]]
forall a. Mutable a => a -> [[a]]
mutiers a
f) ((b, c, d, e, f) -> [[(b, c, d, e, f)]]
forall a. Mutable a => a -> [[a]]
mutiers (b
g,c
h,d
i,e
j,f
k))

-- Further tuple instances are defined on FitSpec.Mutable.Tuples and are
-- exported by default by Test.FitSpec.