{-| Module : Test.Multivariant.Types.Cases Description : Interpreter for corner cases Copyright : (c) Anton Marchenko, Mansur Ziatdinov, 2016-2017 License : BSD-3 Maintainer : gltronred@gmail.com Stability : provisional Portability : POSIX This module provides interpreter for corner cases. -} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeOperators #-} module Test.Multivariant.Types.Cases where import Test.Multivariant.Classes import Control.Arrow import qualified Control.Invertible.BiArrow as BA import Data.Invertible.Bijection import qualified Data.Invertible.Function as Inv import Data.List import Data.Tuple data Case a b = Case { caseTransform :: a<->b , caseCorner :: [(a, b)] } -- | Type of interpreter newtype Cases a b = Cases { unCases :: [Case a b] } -- | Get a list of corner cases for each variant getCases :: (Eq a, Eq b) => Cases a b -- ^ Interpreter -> [[(a,b)]] -- ^ List (for each variant) of lists of pairs of input and output. getCases = nub . map caseCorner . unCases after :: Case a b -> Case b c -> Case a c after (Case f abs) (Case g bcs) = Case (g Inv.. f) $ map (id *** biTo g) abs ++ map (biFrom f *** id) bcs prod :: Case a1 b1 -> Case a2 b2 -> Case (a1,a2) (b1,b2) prod (Case f cs1) (Case g cs2) = Case (f *** g) [ ((a1,a2),(b1,b2)) | (a1,b1) <- cs1, (a2,b2) <- cs2 ] instance Program Cases where step f = Cases [Case f []] a ~> b = Cases [ after ca cb | ca <- unCases a, cb <- unCases b ] a <***> b = Cases [ prod ca cb | ca <- unCases a, cb <- unCases b ] a <+++> b = Cases $ unCases a ++ unCases b appendCases :: [a] -> [b] -> Case a b -> Case a b appendCases as bs (Case f abs) = Case f $ map (id &&& biTo f) as ++ map (biFrom f &&& id) bs ++ abs instance WithCornerCases Cases where withCornerCases f (as,bs) = Cases $ map (appendCases as bs) $ unCases f instance WithInvert Cases where invert (Cases cs) = Cases $ map (\(Case f c) -> Case (BA.invert f) (map swap c)) cs instance WithDescription Cases where withDescription f _ = f