{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module Data.FiberBundle
(
FiberBundle (..)
, SemigroupBundle (..)
, MonoidBundle (..)
, unitOf
, isUnit
, GroupBundle (..)
, AbelianBundle
, BundleMorphism (..)
, monoidBundleMorphism
, prop_SemigroupBundle_combine_base
, prop_SemigroupBundle_combine_associative
, prop_MonoidBundle_unit_left
, prop_MonoidBundle_unit_right
, prop_GroupBundle_inverse_base
, prop_GroupBundle_inverse_combine_left
, prop_GroupBundle_inverse_combine_right
, prop_AbelianBundle_combine_commutative
, prop_BundleMorphism_fiber_preserving
, prop_BundleMorphism_semigroup
, prop_BundleMorphism_monoid
, prop_BundleMorphism_group
) where
import Data.Maybe (fromJust)
class FiberBundle a where
type Base a :: *
base :: a -> Base a
instance (FiberBundle a, FiberBundle b) => FiberBundle (a,b) where
type Base (a,b) = (Base a, Base b)
base (x, y) = (base x, base y)
instance (FiberBundle a, FiberBundle b) => FiberBundle (Either a b) where
type Base (Either a b) = Either (Base a) (Base b)
base (Left x) = Left (base x)
base (Right x) = Right (base x)
class FiberBundle a => SemigroupBundle a where
combine :: a -> a -> Maybe a
unsafeCombine :: a -> a -> a
unsafeCombine x y = fromJust (combine x y)
{-# MINIMAL combine #-}
instance (SemigroupBundle a, SemigroupBundle b) => SemigroupBundle (a,b) where
combine (a1,b1) (a2,b2) = (,) <$> combine a1 a2 <*> combine b1 b2
unsafeCombine (a1,b1) (a2,b2) = (unsafeCombine a1 a2, unsafeCombine b1 b2)
instance (SemigroupBundle a, SemigroupBundle b) => SemigroupBundle (Either a b) where
combine (Left a) (Left b) = Left <$> combine a b
combine (Right a) (Right b) = Right <$> combine a b
combine _ _ = Nothing
unsafeCombine (Left a) (Left b) = Left $ unsafeCombine a b
unsafeCombine (Right a) (Right b) = Right $ unsafeCombine a b
unsafeCombine _ _ = error "unsafeCombine: not in the same fiber"
prop_SemigroupBundle_combine_base ::
(SemigroupBundle a, Eq (Base a)) =>
a -> a -> Bool
prop_SemigroupBundle_combine_base x y =
case combine x y of
Nothing ->
base x /= base y
Just _ ->
base x == base y
prop_SemigroupBundle_combine_associative ::
(SemigroupBundle a, Eq a) =>
a -> a -> a -> Bool
prop_SemigroupBundle_combine_associative x y z =
(combine x y >>= flip combine z) ==
(combine x =<< combine y z)
class SemigroupBundle a => MonoidBundle a where
unit :: Base a -> a
instance (MonoidBundle a, MonoidBundle b) => MonoidBundle (a,b) where
unit (a,b) = (unit a, unit b)
instance (MonoidBundle a, MonoidBundle b) => MonoidBundle (Either a b) where
unit (Left a) = Left (unit a)
unit (Right a) = Right (unit a)
unitOf :: MonoidBundle a => a -> a
unitOf = unit . base
isUnit :: (MonoidBundle a, Eq a) => a -> Bool
isUnit a = a == unitOf a
prop_MonoidBundle_unit_left ::
(MonoidBundle a, Eq a) =>
a -> Bool
prop_MonoidBundle_unit_left x =
combine (unitOf x) x == Just x
prop_MonoidBundle_unit_right ::
(MonoidBundle a, Eq a) =>
a -> Bool
prop_MonoidBundle_unit_right x =
combine x (unitOf x) == Just x
class MonoidBundle a => GroupBundle a where
inverse :: a -> a
instance (GroupBundle a, GroupBundle b) => GroupBundle (a,b) where
inverse (a,b) = (inverse a, inverse b)
instance (GroupBundle a, GroupBundle b) => GroupBundle (Either a b) where
inverse (Left a) = Left (inverse a)
inverse (Right a) = Right (inverse a)
prop_GroupBundle_inverse_base ::
(GroupBundle a, Eq (Base a)) =>
a -> Bool
prop_GroupBundle_inverse_base x =
base (inverse x) == base x
prop_GroupBundle_inverse_combine_left ::
(GroupBundle a, Eq a) =>
a -> Bool
prop_GroupBundle_inverse_combine_left x =
combine (inverse x) x == Just (unitOf x)
prop_GroupBundle_inverse_combine_right ::
(GroupBundle a, Eq a) =>
a -> Bool
prop_GroupBundle_inverse_combine_right x =
combine x (inverse x) == Just (unitOf x)
class SemigroupBundle a => AbelianBundle a where
prop_AbelianBundle_combine_commutative ::
(AbelianBundle a, Eq a) =>
a -> a -> Bool
prop_AbelianBundle_combine_commutative x y =
combine x y == combine y x
data BundleMorphism a b = BundleMorphism (a -> b) (Base a -> Base b)
monoidBundleMorphism ::
(MonoidBundle a, FiberBundle b) => (a -> b) -> BundleMorphism a b
monoidBundleMorphism f = BundleMorphism f (base . f . unit)
prop_BundleMorphism_fiber_preserving ::
(FiberBundle a, FiberBundle b, Eq (Base b)) =>
BundleMorphism a b -> a -> Bool
prop_BundleMorphism_fiber_preserving (BundleMorphism f g) x =
g (base x) == base (f x)
prop_BundleMorphism_semigroup ::
(SemigroupBundle a, SemigroupBundle b, Eq b) =>
BundleMorphism a b -> a -> a -> Bool
prop_BundleMorphism_semigroup (BundleMorphism f _) x y =
combine (f x) (f y) == fmap f (combine x y)
prop_BundleMorphism_monoid ::
(MonoidBundle a, MonoidBundle b, Eq b) =>
BundleMorphism a b -> Base a -> Bool
prop_BundleMorphism_monoid (BundleMorphism f g) x =
f (unit x) == unit (g x)
prop_BundleMorphism_group ::
(GroupBundle a, GroupBundle b, Eq b) =>
BundleMorphism a b -> a -> Bool
prop_BundleMorphism_group (BundleMorphism f _) x =
inverse (f x) == f (inverse x)