def test_traversable_composition(cls, data): """Test composition law of traverse""" # Sample an applicative type constructor from haskpy.typeclasses.applicative import Applicative app_f = data.draw(testing.sample_class(Applicative)) app_g = data.draw(testing.sample_class(Applicative)) # Sample types a = data.draw(testing.sample_hashable_type()) b = data.draw(testing.sample_hashable_type()) c = data.draw(testing.sample_type()) t = data.draw(cls.sample_traversable_type_constructor()) m_f = data.draw(app_f.sample_applicative_type_constructor()) m_g = data.draw(app_g.sample_applicative_type_constructor()) # Sample values x = data.draw(t(a)) f = data.draw(testing.sample_function(m_f(b))) g = data.draw(testing.sample_function(m_g(c))) # Check the law from haskpy import map cls.assert_traversable_traverse_composition(x, f, g, app_f, app_g, data=data) cls.assert_traversable_sequence_composition(map(map(g), x.map(f)), app_f, app_g, data=data) return
def test_profunctor_dimap(cls, data): # Draw types b = data.draw(testing.sample_eq_type()) c = data.draw(testing.sample_eq_type()) d = data.draw(testing.sample_type()) f = data.draw(cls.sample_profunctor_type_constructor()) fbc = f(b, c) # Draw values x = data.draw(fbc) f = data.draw(testing.sample_function(b)) g = data.draw(testing.sample_function(d)) cls.assert_profunctor_dimap(x, f, g, data=data) return
def test_contravariant_composition(cls, data): # Draw types a = data.draw(testing.sample_type()) b = data.draw(testing.sample_eq_type()) c = data.draw(testing.sample_eq_type()) t = data.draw(cls.sample_contravariant_type_constructor()) ta = t(a) # Draw values v = data.draw(ta) f = data.draw(testing.sample_function(b)) g = data.draw(testing.sample_function(c)) cls.assert_contravariant_composition(v, f, g, data=data) return
def test_functor_composition(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_eq_type()) c = data.draw(testing.sample_type()) f = data.draw(cls.sample_functor_type_constructor()) fa = f(a) # Draw values v = data.draw(fa) g = data.draw(testing.sample_function(b)) h = data.draw(testing.sample_function(c)) cls.assert_functor_composition(v, g, h, data=data) return
def test_bind_associativity(cls, data): a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_eq_type()) c = data.draw(testing.sample_type()) m = data.draw(cls.sample_bind_type_constructor()) ma = m(a) mb = m(b) mc = m(c) m = data.draw(ma) f = data.draw(testing.sample_function(mb)) g = data.draw(testing.sample_function(mc)) cls.assert_bind_associativity(m, f, g, data=data) return
def check(app_trans, app1, app2): a = data.draw(testing.sample_hashable_type()) b = data.draw(testing.sample_type()) t = data.draw(cls.sample_traversable_type_constructor()) f = data.draw(app1.sample_applicative_type_constructor()) x = data.draw(t(a)) g = data.draw(testing.sample_function(f(b))) cls.assert_traversable_traverse_naturality( x, g, app_trans, app1, app2, data=data, ) cls.assert_traversable_sequence_naturality( x.map(g), app_trans, app1, app2, data=data, ) return
def test_foldable_foldl(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_eq_type()) f = data.draw(cls.sample_foldable_type_constructor()) fa = f(a) # Draw values xs = data.draw(fa) initial = data.draw(b) g = data.draw(testing.sample_function(testing.sample_function(b))) with catch_warnings(): filterwarnings("ignore", category=PerformanceWarning) cls.assert_foldable_foldl(xs, g, initial, data=data) return
def test_applicative_composition(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_eq_type()) c = data.draw(testing.sample_type()) f = data.draw(cls.sample_applicative_type_constructor()) fa = f(a) fab = f(testing.sample_function(b)) fbc = f(testing.sample_function(c)) # Draw values w = data.draw(fa) v = data.draw(fab) u = data.draw(fbc) cls.assert_applicative_composition(u, v, w, data=data) return
def test_applicative_homomorphism(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) # Draw values x = data.draw(a) f = data.draw(testing.sample_function(b)) cls.assert_applicative_homomorphism(f, x, data=data) return
def test_function_type_in_endo(data): """Test functions as the input/output type of endo functions This needs to be written manually because functions aren't hashable so we cannot use them as the input type of functions automatically. Endofunction has type ``a -> a``. This test will use ``(a -> b) -> (a -> b)``. """ def scale_output(f): def scaled(x): return f(x) * 3 return Function(scaled) Endo.assert_monoid_identity(Endo(scale_output), data=data, input_strategy=testing.sample_function( st.integers())) def translate_output(f): def translated(x): return f(x) + 3 return Function(translated) def exponentiate_output(f): def translated(x): return f(x)**3 return Function(translated) Endo.assert_semigroup_associativity(Endo(scale_output), Endo(exponentiate_output), Endo(translate_output), data=data, input_strategy=testing.sample_function( st.integers())) return
def test_profunctor_contramap(cls, data): # Draw types b = data.draw(testing.sample_eq_type()) d = data.draw(testing.sample_type()) f = data.draw(cls.sample_profunctor_type_constructor()) fbd = f(b, d) # Draw values x = data.draw(fbd) f = data.draw(testing.sample_function(b)) cls.assert_profunctor_contramap(x, f, data=data) return
def test_monad_left_identity(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) m = data.draw(cls.sample_monad_type_constructor()) mb = m(b) # Draw values f = data.draw(testing.sample_function(mb)) x = data.draw(a) cls.assert_monad_left_identity(f, x, data=data) return
def test_functor_map(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) f = data.draw(cls.sample_functor_type_constructor()) fa = f(a) # Draw values v = data.draw(fa) f = data.draw(testing.sample_function(b)) cls.assert_functor_map(v, f, data=data) return
def test_monad_map(cls, data): """Test consistency of ``map`` with the default implementation""" # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) m = data.draw(cls.sample_monad_type_constructor()) ma = m(a) u = data.draw(ma) f = data.draw(testing.sample_function(b)) cls.assert_monad_map(u, f, data=data) return
def test_applicative_interchange(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) f = data.draw(cls.sample_applicative_type_constructor()) fab = f(testing.sample_function(b)) # Draw values y = data.draw(a) u = data.draw(fab) cls.assert_applicative_interchange(u, y, data=data) return
def test_applicative_map(cls, data): """Test consistency between Applicative and Functor implementations""" # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) f = data.draw(cls.sample_applicative_type_constructor()) fa = f(a) # Draw values v = data.draw(fa) f = data.draw(testing.sample_function(b)) cls.assert_applicative_map(v, f, data=data) return
def test_apply_apply(cls, data): # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) f = data.draw(cls.sample_apply_type_constructor()) fa = f(a) fab = f(testing.sample_function(b)) # Draw values v = data.draw(fa) u = data.draw(fab) cls.assert_apply_apply(u, v, data=data) return
def test_bind_apply(cls, data): """Test consistency ``apply`` with the default implementations""" # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) m = data.draw(cls.sample_bind_type_constructor()) ma = m(a) mab = m(testing.sample_function(b)) # Draw values v = data.draw(ma) u = data.draw(mab) cls.assert_bind_apply(u, v, data=data) return
def test_bind_bind(cls, data): """Test consistency of ``bind`` with the default implementation""" # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) m = data.draw(cls.sample_bind_type_constructor()) ma = m(a) mb = m(b) # Draw values u = data.draw(ma) f = data.draw(testing.sample_function(mb)) cls.assert_bind_bind(u, f, data=data) return
def test_foldable_fold_map(cls, data): # Draw types from haskpy.typeclasses import Monoid monoid = data.draw(testing.sample_class(Monoid)) a = data.draw(testing.sample_eq_type()) b = data.draw(monoid.sample_monoid_type()) f = data.draw(cls.sample_foldable_type_constructor()) fa = f(a) # Draw values f = data.draw(testing.sample_function(b)) xs = data.draw(fa) cls.assert_foldable_fold_map(xs, monoid, f, data=data) return
def test_eq_substitutivity(cls, data): """Test if ``x == y = True``, then ``f(x) == f(y) = True``""" # Draw types a = data.draw(cls.sample_eq_type()) b = data.draw(testing.sample_eq_type()) # Draw values x = data.draw(a) y = data.draw(a) f = data.draw(testing.sample_function(b)) # Note: the only requirement for arbitrary functions is that the input # variable has __eq__ implemented. And we have that for Eq type so this # test can always be run. cls.assert_eq_substitutivity(x, y, f) return
def test_foldable_functor(cls, data): from .functor import Functor import pytest if not issubclass(cls, Functor): pytest.skip("{0} not Functor".format(cls.__name__)) # Draw types from haskpy.typeclasses import Monoid monoid = data.draw(testing.sample_class(Monoid)) b = data.draw(monoid.sample_monoid_type()) a = data.draw(testing.sample_eq_type()) f = data.draw(cls.sample_foldable_functor_type_constructor()) fa = f(a) # Draw values f = data.draw(testing.sample_function(b)) xs = data.draw(fa) cls.assert_foldable_functor(xs, monoid, f, data=data) return
def test_traversable_traverse(cls, data): """Test traverse based on the default implementation The default implementation defines the law with respect to sequence. """ # Sample an applicative type constructor from haskpy.typeclasses.applicative import Applicative app = data.draw(testing.sample_class(Applicative)) # Sample types a = data.draw(testing.sample_hashable_type()) b = data.draw(testing.sample_hashable_type()) t = data.draw(cls.sample_traversable_type_constructor()) f = data.draw(app.sample_applicative_type_constructor()) # Sample values x = data.draw(t(a)) g = data.draw(testing.sample_function(f(b))) # Check the law cls.assert_traversable_traverse(app, x, g, data=data) return
def sample_value(cls, a): return testing.sample_function(a).map(lambda f: Endo(f))