gambler-0.4.0.0: test/Spec/Effectful.hs
module Spec.Effectful where
import Fold.Effectful
import Test.Hspec
import Control.Applicative (pure, (<*>))
import Control.Monad ((<=<))
import Data.Bool (Bool (..))
import Data.Foldable (traverse_)
import Data.Function (id, on, (.), (&))
import Data.Functor ((<$>))
import Data.Functor.Identity (Identity (Identity), runIdentity)
import Data.Monoid (mempty)
import Data.Semigroup (Sum (Sum), (<>))
import Prelude ((>), String, Integer, (+), (*))
import qualified Data.List as List
spec :: SpecWith ()
spec = describe "EffectfulFold" do
describe "drop" do
it "run (drop n f) xs = run f (List.drop n xs)" do
let xs = [10, 20, 30, 1, 2, 3] :: [Integer]
f = sum :: EffectfulFold Identity Integer Integer
[0 .. 8] & traverse_ @[] \n ->
run (drop n f) xs `shouldBe` run f (List.genericDrop n xs)
describe "effectMonoid" do
it "If <> is commutative, \
\effectMonoid (f <> g) = effectMonoid f <> effectMonoid g" do
let xs = [(1, 3), (5, 4), (11, 23)] :: [(Integer, Integer)]
f (x, _) = pure (Sum x)
g (_, x) = pure (Sum x)
(===) = shouldBe `on` \fo ->
runIdentity (run fo xs)
effectMonoid (f <> g)
=== (effectMonoid f <> effectMonoid g)
it "effectMonoid mempty = mempty" do
let xs = ["one", "two", "three"] :: [String]
(===) = shouldBe `on` \fo ->
runIdentity (run fo xs) :: Sum Integer
effectMonoid mempty === mempty
describe "premap" do
it "premap pure = id" do
let xs = [5, 13, 1] :: [Integer]
(===) = shouldBe `on` \f ->
runIdentity (run (f sum) xs) :: Integer
premap pure === id
it "premap (f <=< g) = premap g . premap f" do
let xs = [5, 13, 1] :: [Integer]
f = Identity . (+ 13)
g = Identity . (* 7)
(===) = shouldBe `on` \h ->
runIdentity (run (h list) xs) :: [Integer]
premap (f <=< g) === (premap g . premap f)
it "premap k (pure r) = pure r" do
let xs = [5, 13, 1] :: [Integer]
k = Identity . (+ 13)
r = "Hi." :: String
(===) = shouldBe `on` \fo ->
runIdentity (run fo xs) :: String
premap k (pure r) === pure r
it "premap k (f <*> x) = premap k f <*> premap k x" do
let xs = [1..10] :: [Integer]
k = Identity . (+ 7)
f = (+) <$> sum
x = product
(===) = shouldBe `on` \fo ->
runIdentity (run fo xs)
premap k (f <*> x) === (premap k f <*> premap k x)
describe "prefilter" do
it "considers only inputs that match an effectful predicate" do
let xs = [1..10] :: [Integer]
p = (> 5)
f = sum
shouldBe @(Identity Integer)
(run (prefilter (Identity . p) f) xs)
(run f (List.filter p xs))
describe "null" do
it "True for []" do
run null ([] :: [Integer]) `shouldBe` Identity True
it "False for anything else" do
run null ([1] :: [Integer]) `shouldBe` Identity False
run null ([1,2] :: [Integer]) `shouldBe` Identity False
run null ([1,2,3] :: [Integer]) `shouldBe` Identity False