Source code for haskpy.typeclasses._cocartesian

from hypothesis import given
from hypothesis import strategies as st

from haskpy.internal import class_function
from haskpy.testing import assert_output
from haskpy import testing

# Use the "hidden" module in order to avoid circular imports
from ._profunctor import Profunctor


[docs]class Cocartesian(Profunctor): """Cocartesian profunctor Perhaps better known as Choice in Haskell: https://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor-Choice.html I decided to use name Cocartesian because that was used in the profunctor optics paper. Minimal complete definition: ``left | right``. """
[docs] def left(self): return self.right().dimap(_flip_either, _flip_either)
[docs] def right(self): return self.left().dimap(_flip_either, _flip_either)
# # Test Cocartesian laws # @class_function @assert_output def assert_cocartesian_unit(cls, h): from haskpy import Left lzero = lambda ea: ea.match(Left=lambda a: a, Right=lambda _: None) rzero = lambda a: Left(a) return ( h.dimap(lzero, rzero), h.left(), ) @class_function @given(st.data()) def test_cocartesian_unit(cls, data): from haskpy import Left # Draw types a = data.draw(testing.sample_eq_type()) b = data.draw(testing.sample_type()) fab = data.draw(cls.sample_profunctor_type(a, b)) # Draw values h = data.draw(fab) cls.assert_cocartesian_unit( h, data=data, input_strategy=a.map(Left), ) return @class_function @assert_output def assert_cocartesian_associativity(cls, h): from haskpy.types.either import Left, Right lcoassoc = lambda a_bc: a_bc.match( Left=lambda a: Left(Left(a)), Right=lambda bc: bc.match( Left=lambda b: Left(Right(b)), Right=lambda c: Right(c) ) ) rcoassoc = lambda ab_c: ab_c.match( Left=lambda ab: ab.match( Left=lambda a: Left(a), Right=lambda b: Right(Left(b)), ), Right=lambda c: Right(Right(c)) ) return ( h.left().left().dimap(lcoassoc, rcoassoc), h.left(), ) @class_function @given(st.data()) def test_cocartesian_associativity(cls, data): from haskpy.types.either import Either # Draw types a = Either.sample_value( data.draw(testing.sample_eq_type()), Either.sample_value( st.just("foo"), st.just("bar"), ) ) b = data.draw(testing.sample_type()) fab = data.draw(cls.sample_profunctor_type(a, b)) # Draw values h = data.draw(fab) cls.assert_cocartesian_associativity(h, data=data, input_strategy=a) return # # Test laws based on default implementations # @class_function @assert_output def assert_cocartesian_left(cls, x): return ( Cocartesian.left(x), x.left(), ) @class_function @given(st.data()) def test_cocartesian_left(cls, data): from haskpy.types.either import Either # Draw types a1 = data.draw(testing.sample_eq_type()) a2 = data.draw(testing.sample_eq_type()) a = Either.sample_value(a1, a2) b = data.draw(testing.sample_type()) fab = data.draw(cls.sample_profunctor_type(a, b)) # Draw values x = data.draw(fab) cls.assert_cocartesian_left( x, data=data, input_strategy=a, ) return @class_function @assert_output def assert_cocartesian_right(cls, x): return ( Cocartesian.right(x), x.right(), ) @class_function @given(st.data()) def test_cocartesian_right(cls, data): from haskpy.types.either import Either # Draw types a1 = data.draw(testing.sample_eq_type()) a2 = data.draw(testing.sample_eq_type()) a = Either.sample_value(a1, a2) b = data.draw(testing.sample_type()) fab = data.draw(cls.sample_profunctor_type(a, b)) # Draw values x = data.draw(fab) cls.assert_cocartesian_right( x, data=data, input_strategy=a, ) return
def _flip_either(x): from haskpy.types.either import Left, Right return x.match( Left=lambda a: Right(a), Right=lambda b: Left(b), )