module Main (main) where import Control.Applicative (liftA2) import Data.Foldable import qualified Data.Map.Strict as Map import Data.Monoid import Data.Semiring import Data.Semiring.Free import Data.Semiring.Numeric import Data.Set (Set) import Data.Word (Word8) import Test.DocTest import Test.QuickCheck import Test.Semiring smallCheck :: Testable prop => prop -> IO () smallCheck = quickCheckWith (stdArgs { maxSuccess = 40, maxSize = 30}) instance (Enum a, Bounded a, Ord a, Ord b, Semiring b) => Semiring (Func a b) where zero = fromFunc zero one = fromFunc one f <+> g = fromFunc (apply f <+> apply g) f <.> g = fromFunc (apply f <.> apply g) main :: IO () main = do quickCheck (semiringLaws :: Laws (Func Word8 Word8)) quickCheck (semiringLaws :: Laws ()) quickCheck (semiringLaws :: Laws Bool) quickCheck (forAll arbitrary (\(x,y,z) -> semiringLaws (Any x) (Any y) (Any z))) quickCheck (forAll arbitrary (\(x,y,z) -> semiringLaws (All x) (All y) (All z))) quickCheck (semiringLaws :: Laws ()) quickCheck (semiringLaws :: Laws Integer) smallCheck (semiringLaws :: Laws (Set (Add Integer))) smallCheck (semiringLaws :: Laws [Integer]) quickCheck (semiringLaws :: Laws (Max Integer)) quickCheck (semiringLaws :: Laws (Min Integer)) quickCheck (semiringLaws :: Laws (Integer,Integer)) quickCheck (semiringLaws :: Laws (Integer,Integer,Integer)) quickCheck (semiringLaws :: Laws (Integer,Integer,Integer,Integer)) quickCheck (semiringLaws :: Laws (Integer,Integer,Integer,Integer,Integer)) smallCheck (semiringLaws :: Laws (Free Integer)) quickCheck (semiringLaws :: Laws (Bottleneck Word8)) quickCheck (semiringLaws :: Laws (Division Integer)) quickCheck (semiringLaws :: Laws (Ɓukasiewicz Integer)) quickCheck (semiringLaws :: Laws (Viterbi Integer)) doctest [ "-isrc" , "src/Data/Semiring.hs" , "src/Data/Semiring/Numeric.hs" , "src/Test/Semiring.hs" , "src/Data/Semiring/Free.hs" ] data Func a b = Func b [(a,b)] deriving (Eq, Ord) instance (Show a, Show b) => Show (Func a b) where showsPrec _ (Func c xs) = showChar '{' . foldr f b xs where f (x,y) a = shows x . showString " -> " . shows y . showString ", " . a b = showString "_ -> " . shows c . showChar '}' apply :: Ord a => Func a b -> a -> b apply (Func c cs) x = foldr f c cs where f (e,y) a = case compare x e of LT -> c EQ -> y GT -> a instance (Ord a, Eq b, Arbitrary a, Arbitrary b) => Arbitrary (Func a b) where arbitrary = liftA2 fromList arbitrary arbitrary shrink (Func c xs) = map (fromList c) (shrink xs) fromList :: (Ord a, Eq b) => b -> [(a,b)] -> Func a b fromList cnst = Func cnst . Map.toList . Map.fromList . filter ((cnst/=) . snd) fromFunc :: (Enum a, Bounded a, Ord a, Ord b) => (a -> b) -> Func a b fromFunc f = fromList cnst (zip xs ys) where xs = [minBound..maxBound] ys = map f xs Just cnst = mostFrequent ys mostFrequent :: (Ord a, Foldable f) => f a -> Maybe a mostFrequent = fmap fst . fst . foldl' f (Nothing, Map.empty :: Map.Map a Int) where f (b,m) e = (Just nb, Map.insert e c m) where c = maybe 1 succ (Map.lookup e m) nb = case b of Just (a,d) | d >= c -> (a,d) _ -> (e,c)