<commit_before>-- | Enumeration of function mutations
module FitSpec.Mutable
  ( Mutable (..)
  , tMutantsEq
  , mutantsIntegral
  )
where

import Test.Check
import Data.List (intercalate, delete)
import Data.Maybe
import Test.Check.Error (errorToNothing)

-- | 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 values with no 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 null mutant, of size 0,
--   the second tier contains mutants of size 1,
--   the third  tier contains mutants of size 2,
--   and so on.
--
-- The null 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.
class Mutable a where
  tMutants :: a -> [[a]]
  mutants :: a -> [a]
  tMutants = map (:[]) . mutants
  mutants = concat . tMutants
  {-# MINIMAL mutants | tMutants #-}


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

-- | Implementation of 'tMutants' for non-functional data types.
-- To declare:
--
-- > instance MyData where tMutants = tMutantsEq
-- > instance (Eq a, Eq b) => MyDt a b where tMutants = tMutantsEq
--
-- Examples:
--
-- > tMutantsEq True = [[True], [False]]
-- > tMutantsEq 2    = [[2], [0], [1], [], [3], [4], ...
-- > tMutantsEq [1]  = [ [[1]], [[]], [[0]], [[0,0]], ...
tMutantsEq :: (Listable a, Eq a) => a -> [[a]]
tMutantsEq x = [x] : tdelete x tiers  -- possible optimization: (tdeleteOnce x)

tdelete :: Eq a => a -> [[a]] -> [[a]]
tdelete x = tnormalize . map (delete x)
  where tnormalize []       = []
        tnormalize [[]]     = []
        tnormalize (xs:xss) = xs:tnormalize xss

-- Instances for (non-functional) data types
instance Mutable ()   where tMutants = tMutantsEq
instance Mutable Int  where tMutants = tMutantsEq
instance Mutable Char where tMutants = tMutantsEq
instance Mutable Bool where tMutants = tMutantsEq
instance (Eq a, Listable a) => Mutable [a]       where tMutants = tMutantsEq
instance (Eq a, Listable a) => Mutable (Maybe a) where tMutants = tMutantsEq

-- Mutants of an Integral value.  Always start towards zero.  Alternating
-- between sucessor and predecessor.
-- The tail usage is there to avoid generating out of bound values.
-- (x-1) is usually safe though.
mutantsIntegral :: Integral a => a -> [a]
mutantsIntegral i | i > 0     = [i..] +| tail [i,(i-1)..]
                  | otherwise = [i,(i-1)..] +| tail [i..]
-- instance Mutable Int  where mutants = mutantsIntegral

{- Alternative implementation for Mutable lists:
instance (Listable a, Mutable a) => Mutable [a]
  where tMutants []     = [ [] ]
                         : [ ]
                         : tail listing
        tMutants (x:xs) = [ (x:xs) ]
                         : [ [] ]
                         : tail (lsProductWith (:) (tMutants x) (tMutants 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 f (x',fx') = \x -> if x == x'
                         then fx'<commit_msg>Comment-out unused section.<commit_after>-- | Enumeration of function mutations
module FitSpec.Mutable
  ( Mutable (..)
  , tMutantsEq
--, mutantsIntegral
  )
where

import Test.Check
import Data.List (intercalate, delete)
import Data.Maybe
import Test.Check.Error (errorToNothing)

-- | 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 values with no 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 null mutant, of size 0,
--   the second tier contains mutants of size 1,
--   the third  tier contains mutants of size 2,
--   and so on.
--
-- The null 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.
class Mutable a where
  tMutants :: a -> [[a]]
  mutants :: a -> [a]
  tMutants = map (:[]) . mutants
  mutants = concat . tMutants
  {-# MINIMAL mutants | tMutants #-}


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

-- | Implementation of 'tMutants' for non-functional data types.
-- To declare:
--
-- > instance MyData where tMutants = tMutantsEq
-- > instance (Eq a, Eq b) => MyDt a b where tMutants = tMutantsEq
--
-- Examples:
--
-- > tMutantsEq True = [[True], [False]]
-- > tMutantsEq 2    = [[2], [0], [1], [], [3], [4], ...
-- > tMutantsEq [1]  = [ [[1]], [[]], [[0]], [[0,0]], ...
tMutantsEq :: (Listable a, Eq a) => a -> [[a]]
tMutantsEq x = [x] : tdelete x tiers  -- possible optimization: (tdeleteOnce x)

tdelete :: Eq a => a -> [[a]] -> [[a]]
tdelete x = tnormalize . map (delete x)
  where tnormalize []       = []
        tnormalize [[]]     = []
        tnormalize (xs:xss) = xs:tnormalize xss

-- Instances for (non-functional) data types
instance Mutable ()   where tMutants = tMutantsEq
instance Mutable Int  where tMutants = tMutantsEq
instance Mutable Char where tMutants = tMutantsEq
instance Mutable Bool where tMutants = tMutantsEq
instance (Eq a, Listable a) => Mutable [a]       where tMutants = tMutantsEq
instance (Eq a, Listable a) => Mutable (Maybe a) where tMutants = tMutantsEq

{- 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 tMutants []     = [ [] ]
                        : [ ]
                        : tail tiers
        tMutants (x:xs) = [ (x:xs) ]
                        : [ [] ]
                        : tail (lsProductWith (:) (tMutants x) (tMutants 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 f (x',fx') = \x -> if x == x'
                         then fx'
{'fraction_non_alphanumeric': 0.14614285714285713, 'fraction_numerical': 0.0064285714285714285, 'mean_word_length': 2.5057586379569354, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4113651', 'n_tokens_mistral': 2317, 'n_tokens_neox': 2207, 'n_words': 844}