{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Fake.Cover
( gcover
, Coverage(..)
, Cover(..)
) where
import Control.Applicative
import GHC.Generics as G
import Fake.Types
newtype Coverage a = Coverage { unCoverage :: [FGen a] }
deriving (Functor)
instance Applicative Coverage where
pure = Coverage . pure . pure
Coverage as <*> Coverage bs = Coverage $ zipWith (<*>)
(as ++ take (newlen - alen) (cycle as))
(bs ++ take (newlen - blen) (cycle bs))
where
alen = length as
blen = length bs
newlen = max alen blen
instance Alternative Coverage where
empty = Coverage empty
Coverage as <|> Coverage bs = Coverage (as ++ bs)
class Cover a where
cover :: Coverage a
default cover :: (Generic a, GCover ga, ga ~ G.Rep a) => Coverage a
cover = gcover
instance Cover () where
cover = gcover
instance Cover a => Cover (Maybe a) where
cover = gcover
instance (Cover a, Cover b) => Cover (Either a b) where
cover = gcover
instance (Cover a, Cover b) => Cover (a,b) where
cover = gcover
instance (Cover a, Cover b, Cover c) => Cover (a,b,c) where
cover = gcover
instance (Cover a, Cover b, Cover c, Cover d) => Cover (a,b,c,d) where
cover = gcover
instance (Cover a, Cover b, Cover c, Cover d, Cover e)
=> Cover (a,b,c,d,e) where
cover = gcover
instance (Cover a, Cover b, Cover c, Cover d, Cover e, Cover f)
=> Cover (a,b,c,d,e,f) where
cover = gcover
instance (Cover a, Cover b, Cover c, Cover d, Cover e, Cover f, Cover g)
=> Cover (a,b,c,d,e,f,g) where
cover = gcover
gcover :: (Generic a, GCover ga, ga ~ G.Rep a) => Coverage a
gcover = Coverage $ fmap G.to <$> genericCover
class GCover a where
genericCover :: [FGen (a x)]
instance GCover G.U1 where
genericCover = pure $ pure G.U1
instance Cover c => GCover (G.K1 i c) where
genericCover = fmap G.K1 <$> unCoverage cover
instance GCover f => GCover (G.M1 i c f) where
genericCover = fmap G.M1 <$> genericCover
instance (GCover a, GCover b) => GCover (a G.:*: b) where
genericCover = unCoverage $
(G.:*:) <$> Coverage genericCover <*> Coverage genericCover
instance (GCover a, GCover b) => GCover (a G.:+: b) where
genericCover = unCoverage $
(G.L1 <$> Coverage genericCover) <|> (G.R1 <$> Coverage genericCover)