packages feed

prolens-0.0.0.1: test/Test/Data.hs

module Test.Data
    ( -- * Lenses
      Haskeller (..)
    , nameL
    , knowledgeL

    , Knowledge (..)
    , syntaxL

    , me

      -- * Prisms
    , Grade (..)
    , _Mark

    , gradeMark
    , gradeOther

      -- * Generators
    , genFun
    , genFunction
    , genForget
    , genHaskeller
    , genInt
    , genKnowledge
    , genName
    ) where

import Test.Hspec.Hedgehog (MonadGen)

import Prolens (Forget (..), Fun (..), Lens', Prism', lens, prism')

import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range


data Haskeller = Haskeller
    { haskellerName       :: String
    , haskellerExperience :: Int
    , haskellerKnowledge  :: Knowledge
    } deriving stock (Show, Eq)

data Knowledge = Knowledge
    { kSyntax         :: Bool
    , kMonads         :: Bool
    , kLens           :: Bool
    , kTypeLevelMagic :: Bool
    , kNix            :: Bool
    } deriving stock (Show, Eq)

me :: Haskeller
me = Haskeller
    { haskellerName = "Veronika"
    , haskellerExperience = 2
    , haskellerKnowledge = Knowledge
        { kSyntax = True
        , kMonads = True
        , kLens = True
        , kTypeLevelMagic = True
        , kNix = False
        }
    }

nameL :: Lens' Haskeller String
nameL = lens haskellerName (\h new -> h { haskellerName = new })
{-# INLINE nameL #-}

knowledgeL :: Lens' Haskeller Knowledge
knowledgeL = lens haskellerKnowledge (\h new -> h { haskellerKnowledge = new })
{-# INLINE knowledgeL #-}

syntaxL :: Lens' Knowledge Bool
syntaxL = lens kSyntax (\k new -> k { kSyntax = new })
{-# INLINE syntaxL #-}

data Grade
    = Mark Int
    | Other String
    deriving stock (Show, Eq)

_Mark :: Prism' Grade Int
_Mark = prism' Mark $ \case
    Mark a -> Just a
    _other -> Nothing
{-# INLINE _Mark #-}

gradeMark :: Grade
gradeMark = Mark 5

gradeOther :: Grade
gradeOther = Other "Satisfactory"

-- Generators

genKnowledge :: (MonadGen m) => m Knowledge
genKnowledge = do
    kSyntax <- Gen.bool
    kMonads <- Gen.bool
    kLens <- Gen.bool
    kTypeLevelMagic <- Gen.bool
    kNix <- Gen.bool
    pure Knowledge{..}

genHaskeller :: (MonadGen m) => m Haskeller
genHaskeller = do
    haskellerName <- genName
    haskellerExperience <- Gen.int $ Range.linear 0 50
    haskellerKnowledge <- genKnowledge
    pure Haskeller{..}

genName :: MonadGen m => m String
genName = Gen.string (Range.linear 1 50) Gen.alphaNum

genInt :: MonadGen m => m Int
genInt = Gen.enumBounded

genFunction :: MonadGen m => m (Int -> Int)
genFunction = genInt >>= \n -> Gen.element
    [ id
    , const n
    , (+ n)
    , (* n)
    , subtract n
    , \x -> if x >= n then 1 else 0
    ]

genFun :: MonadGen m => m (Fun Maybe Int Int)
genFun = genFunction >>= \f -> Gen.element $ map Fun
    [ Just
    , const Nothing
    , Just . f
    ]

genForget :: MonadGen m => m (Forget Int Int a)
genForget = Forget . unFun <$> genFun