Source code for haskpy.typeclasses.semigroup
import hypothesis.strategies as st
from hypothesis import given
from .typeclass import Type
from haskpy.utils import (
assert_output,
class_function,
abstract_function,
abstract_class_function,
)
[docs]class Semigroup(Type):
"""Semigroup typeclass
Minimal complete definition:
..
append
For property tests:
..
sample_semigroup_type
"""
[docs] @abstract_function
def append(self, x):
"""m -> m -> m"""
#
# Sampling methods for property tests
#
@abstract_class_function
def sample_semigroup_type(cls):
pass
#
# Test Semigroup laws
#
@class_function
@given(st.data())
def test_semigroup_associativity(cls, data):
"""Test semigroup associativity law"""
# Draw types
t = data.draw(cls.sample_semigroup_type())
# Draw values
x = data.draw(t)
y = data.draw(t)
z = data.draw(t)
cls.assert_semigroup_associativity(x, y, z, data=data)
return
@class_function
@assert_output
def assert_semigroup_associativity(cls, x, y, z):
"""x <> (y <> z) = (x <> y) <> z"""
return (
x.append(y).append(z),
x.append(y.append(z)),
)
[docs]class Commutative(Semigroup):
"""Semigroup following commutativity law
This typeclass doesn't add any features nor methods. It only adds a test
for the commutativity law.
Minimal complete definition:
..
append
For property tests:
..
sample_semigroup_type & sample_commutative_type
"""
#
# Sampling methods for property tests
#
@abstract_class_function
def sample_commutative_type(cls):
pass
#
# Test Commutative laws
#
@class_function
@assert_output
def assert_commutative_commutativity(cls, x, y):
return (x.append(y), y.append(x))
@class_function
@given(st.data())
def test_commutative_commutativity(cls, data):
# Draw types
t = data.draw(cls.sample_commutative_type())
# Draw values
x = data.draw(t)
y = data.draw(t)
cls.assert_commutative_commutativity(x, y, data=data)
return
# Semigroup-related functions are defined in function module because of
# circular dependency.