packages feed

valuations 0.0.3 → 0.0.4

raw patch · 17 files changed

+1534/−672 lines, 17 filesdep +process

Dependencies added: process

Files

changelog.md view
@@ -1,3 +1,16 @@+0.0.4++* Generalise data types over the Profunctor and not (->)+* Add `CovariantFunctor` module — reified covariant functor, dual of `Presheaf`+* Add composition functions for `Presheaf` and `CovariantFunctor`:+  - `composePresheafFunctor` (contravariant ∘ covariant = contravariant)+  - `composeFunctorPresheaf` (covariant ∘ contravariant = contravariant)+  - `composePresheaf` (contravariant ∘ contravariant = covariant)+  - `composeFunctor` (covariant ∘ covariant = covariant)+* Add law-checking functions for `Presheaf` (identity, composition)+* Add law-checking functions for `CovariantFunctor` (identity, composition)+* Update documentation and doctests+ 0.0.3  * Generalise data types over the Profunctor and not (->)
src/Data/Valuation.hs view
@@ -5,80 +5,83 @@ -- based on the valuation algebra framework of Shenoy & Shafer (1990), -- Kohlas (2003), and Abramsky & Carù (2019). --+-- All core types are generalised over profunctors (@p@, @q@, @r@, @s@).+-- When these are @(->)@, each type specialises to an ordinary function;+-- primed type aliases (e.g. 'Semigroup'', 'PartialOrder'') provide+-- these specialisations.+-- -- == Type Hierarchy -- -- === Data Types -- -- @--- 'BinaryFunctionT' f a b        -- a -> a -> f b---   |---   +-- 'BinaryFunction' a b     -- a -> a -> b          (f ~ 'Data.Functor.Identity.Identity')---   |     |---   |     +-- 'Magma' a          -- a -> a -> a          (a ~ b)---   |---   +-- 'MagmaT' f a             -- a -> a -> f a        (a ~ b)+-- 'Semigroup' p a                       -- p a (p a a)+-- 'Semigroup'' a                        -- a -> a -> a          (p ~ (->)) ----- 'Semigroup' a                   -- a -> a -> a+-- 'PartialOrder' p a                    -- p a (p a ('Maybe' 'Ordering'))+-- 'PartialOrder'' a                     -- a -> a -> 'Maybe' 'Ordering'   (p ~ (->)) ----- 'PartialOrder' a                -- a -> a -> 'Maybe' 'Ordering'+-- 'Poset' p a                           -- p a (p a 'Bool')+-- 'Poset'' a                            -- a -> a -> 'Bool'              (p ~ (->)) ----- 'ProjectValuation' v set var    -- set var -> v -> v+-- 'ProjectValuation' p q v set var      -- p (set var) (q v v)+-- 'ProjectValuation'' v set var         -- set var -> v -> v    (p ~ (->), q ~ (->)) ----- 'SemiValuationAlgebra' v set var---   = 'SemiValuationAlgebra'---       ('Semigroup' v)                   -- how to combine values---       ('ProjectValuation' v set var)    -- how to project over a domain+-- 'ValuationAlgebraOp' p set var v      -- p (set var) v+-- 'ValuationAlgebraOp'' set var v       -- set var -> v         (p ~ (->)) ----- 'ValuationAlgebraOp' set var v      -- set var -> v+-- 'SemiValuationAlgebra' p q r v set var+--   = 'SemiValuationAlgebra'+--       ('Semigroup' p v)                       -- how to combine values+--       ('ProjectValuation' q r v set var)      -- how to project over a domain ----- 'ValuationAlgebra' v set var+-- 'ValuationAlgebra' p q r v set var --   = 'ValuationAlgebra'---       ('SemiValuationAlgebra' v set var)---       ('ValuationAlgebraOp' set var v)  -- unit: identity value for a domain---       ('ValuationAlgebraOp' set var v)  -- zero: annihilating value for a domain+--       ('SemiValuationAlgebra' p q r v set var)+--       ('ValuationAlgebraOp' p set var v)      -- unit: identity value for a domain+--       ('ValuationAlgebraOp' p set var v)      -- zero: annihilating value for a domain ----- 'DomainLattice' sg p+-- 'DomainLattice' p sg o --   = 'DomainLattice'---       ('Semigroup' sg)                  -- join (∨ \/ supremum)---       ('Semigroup' sg)                  -- meet (∧ \/ infimum)---       ('PartialOrder' p)               -- partial order+--       ('Semigroup' p sg)                      -- join (∨ \/ supremum)+--       ('Semigroup' p sg)                      -- meet (∧ \/ infimum)+--       ('PartialOrder' p o)                    -- partial order -- -- 'Valuation' set var a --   = 'Valuation'---       (set var)                       -- domain---       a                               -- information+--       (set var)                               -- domain+--       a                                       -- information ----- 'PresheafValuationAlgebra' v set var+-- 'Presheaf' cat cat' f                -- forall a b. cat a b -> cat' (f b) (f a)+-- 'Presheaf'' f                        -- forall a b. (a -> b) -> f b -> f a  (cat ~ (->), cat' ~ (->))+--+-- 'CovariantFunctor' cat cat' f        -- forall a b. cat a b -> cat' (f a) (f b)+-- 'CovariantFunctor'' f                -- forall a b. (a -> b) -> f a -> f b  (cat ~ (->), cat' ~ (->))+--+-- 'PresheafValuationAlgebra' p q r s v set var --   = 'PresheafValuationAlgebra'---       ('DomainLattice' (set var) (set var))   -- lattice on domains---       ('ValuationAlgebra' v set var)          -- the valuation algebra+--       ('DomainLattice' p (set var) (set var)) -- lattice on domains+--       ('ValuationAlgebra' q r s v set var)    -- the valuation algebra -- @ -- -- === Relationships -- -- @--- 'BinaryFunctionT' ──specialises──> 'Magma' ──iso──> 'Semigroup'---                                                         |+-- 'Semigroup' ──────────────────────────────────────────────────────┐ --                          'ProjectValuation' ────────────+──> 'SemiValuationAlgebra' --                                                                       | --                            'ValuationAlgebraOp' ──────────────────────+──> 'ValuationAlgebra' --                                                                                    | --         'PartialOrder' ──> 'DomainLattice' ────────────────────────────────────────+──> 'PresheafValuationAlgebra'+--+--         'Poset' ──────── (converts to\/from 'PartialOrder') -- @ -- -- == Core Concepts ----- === BinaryFunctionT------ 'BinaryFunctionT' @f a b@ wraps @a -> a -> f b@ — a binary function from two @a@ values to an effectful @b@. It has instances for 'Data.Profunctor.Profunctor', 'Data.Profunctor.Strong', 'Data.Profunctor.Choice', 'Functor', 'Applicative', 'Monad', and more.------ When @f ~ 'Data.Functor.Identity.Identity'@ and @a ~ b@, this specialises to 'Magma' @a@ — a binary operation on @a@.--- -- === Semigroup ----- A reified semigroup: a @newtype@ over @a -> a -> a@ representing an associative binary operation. Unlike 'Prelude.Semigroup' which is a type class (one instance per type), this is a value — multiple semigroups can exist for the same type.------ 'Semigroup' is isomorphic to 'Magma' (and hence @'BinaryFunctionT' 'Data.Functor.Identity.Identity' a a@) via 'HasBinaryFunctionT' \/ 'AsBinaryFunctionT'.+-- A reified semigroup: 'Semigroup' @p a@ wraps @p a (p a a)@, representing an associative binary operation generalised over a profunctor @p@. When @p ~ (->)@, this specialises to 'Semigroup'' @a@ wrapping @a -> a -> a@. Unlike 'Prelude.Semigroup' which is a type class (one instance per type), this is a value — multiple semigroups can exist for the same type. -- -- @ -- import qualified "Data.Valuation.Semigroup" as S@@ -104,13 +107,23 @@ -- -- === PartialOrder ----- 'PartialOrder' @a@ wraps @a -> a -> 'Maybe' 'Ordering'@ — a partial order comparison. Unlike 'Ord' which is total, this supports incomparable elements via 'Nothing'. It is 'Data.Functor.Contravariant.Contravariant', 'Data.Functor.Contravariant.Divisible.Divisible', 'Data.Functor.Contravariant.Divisible.Decidable', and has a lexicographic 'Semigroup'.+-- 'PartialOrder' @p a@ wraps @p a (p a ('Maybe' 'Ordering'))@ — a partial order comparison generalised over a 'Data.Profunctor.Profunctor' @p@. When @p ~ (->)@, this specialises to @a -> a -> 'Maybe' 'Ordering'@ (see 'PartialOrder''). Unlike 'Ord' which is total, this supports incomparable elements via 'Nothing'. It is 'Data.Functor.Contravariant.Contravariant', 'Data.Functor.Contravariant.Divisible.Divisible', 'Data.Functor.Contravariant.Divisible.Decidable', and has a lexicographic 'Semigroup'. ----- 'PartialOrder' is isomorphic to @'BinaryFunctionT' 'Maybe' a 'Ordering'@ via 'HasBinaryFunctionT' \/ 'AsBinaryFunctionT'.+-- === Poset --+-- 'Poset' @p a@ wraps @p a (p a 'Bool')@ — a simplified partial order that only captures the @<=@ relation as a 'Bool', generalised over a 'Data.Profunctor.Profunctor' @p@. When @p ~ (->)@, this specialises to @a -> a -> 'Bool'@ (see 'Poset''). Unlike 'PartialOrder' which distinguishes @LT@, @EQ@, @GT@, and incomparable, 'Poset' only records whether @a <= b@. It is 'Data.Functor.Contravariant.Contravariant', 'Data.Functor.Contravariant.Divisible.Divisible', 'Data.Functor.Contravariant.Divisible.Decidable', and has a conjunction 'Semigroup' (product order). Conversions 'fromPartialOrder' and 'toPartialOrder' bridge between 'Poset'' and 'PartialOrder''.+--+-- === Presheaf+--+-- A reified presheaf: 'Presheaf' @cat f cat'@ wraps @forall a b. cat a b -> cat' (f b) (f a)@, representing a contravariant mapping from a source category @cat@ to a target category @cat'@ acting on a type constructor @f@. When both categories are @(->)@, this specialises to 'Presheaf'' @f@ wrapping @forall a b. (a -> b) -> f b -> f a@, which is exactly 'Data.Functor.Contravariant.contramap'. Unlike 'Data.Functor.Contravariant.Contravariant' which is a type class (one instance per type), this is a value — and it is generalised over the source and target categories. Values are provided for standard types ('Data.Functor.Contravariant.Predicate', 'Data.Functor.Contravariant.Comparison', 'Data.Functor.Contravariant.Equivalence', 'Data.Proxy.Proxy', @'Data.Functor.Const.Const' r@).+--+-- === CovariantFunctor+--+-- A reified covariant functor: 'CovariantFunctor' @cat cat' f@ wraps @forall a b. cat a b -> cat' (f a) (f b)@, representing a covariant mapping from a source category @cat@ to a target category @cat'@ acting on a type constructor @f@. When both categories are @(->)@, this specialises to 'CovariantFunctor'' @f@ wrapping @forall a b. (a -> b) -> f a -> f b@, which is exactly 'fmap'. Unlike 'Functor' which is a type class (one instance per type), this is a value — and it is generalised over the source and target categories. Values are provided for standard types ('Data.Functor.Identity.Identity', 'Maybe', @[]@, 'Data.Proxy.Proxy', @'Data.Functor.Const.Const' r@).+-- -- === ProjectValuation ----- 'ProjectValuation' @v set var@ wraps @set var -> v -> v@. Given a domain of variables and a current value, it produces a new value. It is 'Data.Functor.Contravariant.Contravariant' in @var@, and has 'Data.Functor.Contravariant.Divisible.Divisible' and 'Data.Functor.Contravariant.Divisible.Decidable' instances for combining projections.+-- 'ProjectValuation' @p q v set var@ wraps @p (set var) (q v v)@, generalised over profunctors @p@ (outer) and @q@ (inner). When @p ~ (->)@ and @q ~ (->)@, this specialises to 'ProjectValuation'' @v set var@ wrapping @set var -> v -> v@. Given a domain of variables and a current value, it produces a new value. It is 'Data.Functor.Contravariant.Contravariant' in @var@, and has 'Data.Functor.Contravariant.Divisible.Divisible' and 'Data.Functor.Contravariant.Divisible.Decidable' instances for combining projections. -- -- === Valuation --@@ -118,24 +131,24 @@ -- -- === SemiValuationAlgebra ----- Bundles a 'Semigroup' @v@ with a 'ProjectValuation' @v set var@. This provides everything needed to combine valuations: a way to merge information and a way to project information over a domain.+-- 'SemiValuationAlgebra' @p q r v set var@ bundles a 'Semigroup' @p v@ with a 'ProjectValuation' @q r v set var@. The three profunctor parameters allow the semigroup (@p@) and the projection (@q@, @r@) to use independent profunctors. This provides everything needed to combine valuations: a way to merge information and a way to project information over a domain. -- -- === ValuationAlgebra ----- Extends 'SemiValuationAlgebra' with two additional 'ValuationAlgebraOp' functions:+-- 'ValuationAlgebra' @p q r v set var@ extends 'SemiValuationAlgebra' with two additional 'ValuationAlgebraOp' functions: ----- * __unit__ (@set var -> v@): produces an identity value for a given domain--- * __zero__ (@set var -> v@): produces an annihilating value for a given domain+-- * __unit__ ('ValuationAlgebraOp' @p set var v@): produces an identity value for a given domain+-- * __zero__ ('ValuationAlgebraOp' @p set var v@): produces an annihilating value for a given domain -- -- === DomainLattice ----- 'DomainLattice' @sg p@ packages a lattice structure on domains: join (∨) and meet (∧) as 'Semigroup' values, plus a 'PartialOrder'. The type alias @'DomainLattice'' x = 'DomainLattice' x x@ is provided for the common case where the semigroup and partial order operate on the same type.+-- 'DomainLattice' @p sg o@ packages a lattice structure on domains: join (∨) and meet (∧) as 'Semigroup' @p sg@ values, plus a 'PartialOrder' @p o@. The type aliases @'DomainLattice'' sg o = 'DomainLattice' (->) sg o@ and @'DomainLattice''' x = 'DomainLattice'' x x@ are provided for common cases. -- -- The canonical instance is 'setDomainLattice' using 'Data.Set.union', 'Data.Set.intersection', and 'Data.Set.isSubsetOf'. -- -- === PresheafValuationAlgebra ----- The presheaf formulation of a valuation algebra, following Shenoy & Shafer (1990), Kohlas (2003), and Abramsky & Carù (2019). A 'PresheafValuationAlgebra' bundles a 'DomainLattice' with a 'ValuationAlgebra', providing the full structure needed for local computation on valuations:+-- The presheaf formulation of a valuation algebra, following Shenoy & Shafer (1990), Kohlas (2003), and Abramsky & Carù (2019). 'PresheafValuationAlgebra' @p q r s v set var@ bundles a 'DomainLattice' @p@ with a 'ValuationAlgebra' @q r s@, providing the full structure needed for local computation on valuations. The four profunctor parameters allow the domain lattice (@p@) and the valuation algebra (@q@, @r@, @s@) to use different profunctors. -- -- * 'marginalise' — the presheaf restriction map: project a valuation to a subdomain -- * 'combine' — the combination operation: merge two valuations over the joined domain@@ -151,21 +164,21 @@ -- @ -- -- Combine domains and information independently using two Semigroups -- 'combineVar'---   :: 'Semigroup' (set var) -> 'Semigroup' v+--   :: 'Semigroup'' (set var) -> 'Semigroup'' v --   -> 'Valuation' set var v -> 'Valuation' set var v --   -> 'Valuation' set var v -- -- -- Combine using a 'SemiValuationAlgebra': merge domains, combine information, -- -- then project through the merged domain -- 'combineSemiValuation'---   :: 'Semigroup' (set var) -> 'SemiValuationAlgebra' v set var+--   :: 'Semigroup'' (set var) -> 'SemiValuationAlgebra'' v set var --   -> 'Valuation' set var v -> 'Valuation' set var v --   -> 'Valuation' set var v -- -- -- Combine using a 'ValuationAlgebra': like 'combineSemiValuation', but also -- -- folds in the unit value for the merged domain -- 'combineValuation'---   :: 'Semigroup' (set var) -> 'ValuationAlgebra' v set var+--   :: 'Semigroup'' (set var) -> 'ValuationAlgebra'' v set var --   -> 'Valuation' set var v -> 'Valuation' set var v --   -> 'Valuation' set var v -- @@@ -174,14 +187,16 @@ -- -- == Classy Optics ----- Every data type provides @Has*@ (classy lens) and @As*@ (classy prism) type classes, allowing generic programming over any type that contains or can be constructed from the given structure. For example, 'HasSemigroup' @c a@ provides a lens to a 'Semigroup' @a@ inside any @c@, and 'PresheafValuationAlgebra' has instances for 'HasDomainLattice', 'HasValuationAlgebra', 'HasSemiValuationAlgebra', 'HasSemigroup', and 'HasProjectValuation'.+-- Every data type provides @Has*@ (classy lens) and @As*@ (classy prism) type classes, allowing generic programming over any type that contains or can be constructed from the given structure. For example, 'HasSemigroup' @c p a@ provides a lens to a 'Semigroup' @p a@ inside any @c@, and 'PresheafValuationAlgebra' has instances for 'HasDomainLattice', 'HasValuationAlgebra', 'HasSemiValuationAlgebra', 'HasSemigroup', and 'HasProjectValuation'. -- -- == Modules -- -- * "Data.Valuation" — Re-exports everything--- * "Data.Valuation.BinaryFunction" — 'BinaryFunctionT' and type aliases -- * "Data.Valuation.DomainLattice" — Lattice structure on domains (join, meet, partial order)--- * "Data.Valuation.PartialOrder" — Partial order comparison (@a -> a -> 'Maybe' 'Ordering'@)+-- * "Data.Valuation.PartialOrder" — Partial order comparison (@p a (p a ('Maybe' 'Ordering'))@)+-- * "Data.Valuation.Poset" — Simplified partial order (@p a (p a 'Bool')@)+-- * "Data.Valuation.CovariantFunctor" — Reified covariant functor (@forall a b. cat a b -> cat' (f a) (f b)@)+-- * "Data.Valuation.Presheaf" — Reified presheaf (@forall a b. cat a b -> cat' (f b) (f a)@) -- * "Data.Valuation.PresheafValuationAlgebra" — Presheaf formulation: marginalise, combine, and axiom laws -- * "Data.Valuation.ProjectValuation" — Domain projection -- * "Data.Valuation.Semigroup" — Reified semigroups@@ -194,9 +209,11 @@   ) where -import Data.Valuation.BinaryFunction as V+import Data.Valuation.CovariantFunctor as V import Data.Valuation.DomainLattice as V import Data.Valuation.PartialOrder as V+import Data.Valuation.Poset as V+import Data.Valuation.Presheaf as V import Data.Valuation.PresheafValuationAlgebra as V import Data.Valuation.ProjectValuation as V import Data.Valuation.SemiValuationAlgebra as V
− src/Data/Valuation/BinaryFunction.hs
@@ -1,335 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeOperators #-}-{-# OPTIONS_GHC -Wall -Werror #-}---- | Binary functions over a functor, generalising magmas and semigroups.-module Data.Valuation.BinaryFunction-  ( BinaryFunctionT (..),-    BinaryFunction,-    MagmaT,-    Magma,--    -- * optics-    HasBinaryFunctionT (..),-    AsBinaryFunctionT (..),--    -- * combinators-    binaryFunction,-    semigroupBinaryFunctionT,-  )-where--import Control.Applicative (Alternative (..))-import Control.Lens-  ( Iso,-    Lens',-    Prism',-    Rewrapped,-    Wrapped (..),-    from,-    iso,-    over,-    review,-    view,-    _Wrapped,-  )-import Control.Monad.Fix (MonadFix (..))-import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad.Zip (MonadZip (..))-import Control.Selective (Selective (..), selectM)-import Data.Distributive (Distributive (..))-import Data.Functor.Alt (Alt (..))-import Data.Functor.Apply (Apply (..))-import Data.Functor.Bind (Bind (..))-import Data.Functor.Identity (Identity (..))-import Data.Functor.Plus (Plus (..))-import Data.Profunctor (Choice (..), Profunctor (..), Strong (..))-import Data.Profunctor.Closed (Closed (..))-import Data.Valuation.Semigroup-  ( Semigroup',-    applySemigroup,-    runSemigroup,-  )-import Prelude hiding (Semigroup)-import qualified Prelude---- $setup--- >>> :set -Wno-name-shadowing -Wno-type-defaults---- |--- >>> let BinaryFunctionT f = BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int--- >>> f 3 5--- [8]------ >>> let BinaryFunctionT f = BinaryFunctionT (\x y -> Just (x ++ y)) :: BinaryFunctionT Maybe String String--- >>> f "hello" " world"--- Just "hello world"-newtype BinaryFunctionT f a b-  = BinaryFunctionT (a -> a -> f b)--instance-  (BinaryFunctionT f a b ~ t) =>-  Rewrapped (BinaryFunctionT f' a' b') t--instance Wrapped (BinaryFunctionT f a b) where-  type Unwrapped (BinaryFunctionT f a b) = a -> a -> f b-  _Wrapped' =-    iso (\(BinaryFunctionT x) -> x) BinaryFunctionT---- | A 'BinaryFunctionT' specialised to 'Identity'.-type BinaryFunction a b =-  BinaryFunctionT Identity a b---- | A 'BinaryFunctionT' where the input and output types coincide.-type MagmaT f x =-  BinaryFunctionT f x x---- | A 'BinaryFunction' where the input and output types coincide.-type Magma x =-  BinaryFunction x x---- | Classy lens for types that contain a 'BinaryFunctionT'.-class HasBinaryFunctionT c f a b | c -> f a b where-  binaryFunctionT ::-    Lens' c (BinaryFunctionT f a b)--instance HasBinaryFunctionT (BinaryFunctionT f a b) f a b where-  binaryFunctionT = id---- | Classy prism for types that can be constructed from a 'BinaryFunctionT'.-class AsBinaryFunctionT c f a b | c -> f a b where-  _BinaryFunctionT ::-    Prism' c (BinaryFunctionT f a b)--instance AsBinaryFunctionT (BinaryFunctionT f a b) f a b where-  _BinaryFunctionT = id--instance HasBinaryFunctionT (Semigroup' a) Identity a a where-  binaryFunctionT = applySemigroup . from binaryFunction--instance AsBinaryFunctionT (Semigroup' a) Identity a a where-  _BinaryFunctionT = applySemigroup . from binaryFunction---- | Iso between a 'BinaryFunction' and its underlying binary function.-binaryFunction :: Iso (BinaryFunction a b) (BinaryFunction a' b') (a -> a -> b) (a' -> a' -> b')-binaryFunction = _Wrapped . iso (\k a1 a2 -> runIdentity (k a1 a2)) (\k a1 a2 -> Identity (k a1 a2))---- |--- >>> let BinaryFunctionT f = fmap (*2) (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f 3 5--- [16]------ >>> let BinaryFunctionT f = fmap show (BinaryFunctionT (\x y -> Just (x + y)) :: BinaryFunctionT Maybe Int Int)--- >>> f 3 5--- Just "8"-instance (Functor f) => Functor (BinaryFunctionT f a) where-  fmap g = over _Wrapped (\h a1 a2 -> fmap g (h a1 a2))---- |--- >>> import Data.Functor.Apply ((<.>))--- >>> let BinaryFunctionT f = (BinaryFunctionT (\x y -> [(*x), (*y)]) :: BinaryFunctionT [] Int (Int -> Int)) <.> BinaryFunctionT (\x y -> [x + y, x * y])--- >>> f 3 5--- [24,45,40,75]-apBFT :: (f (b -> c) -> f b -> f c) -> BinaryFunctionT f a (b -> c) -> BinaryFunctionT f a b -> BinaryFunctionT f a c-apBFT ap' (BinaryFunctionT hf) (BinaryFunctionT ha) = BinaryFunctionT (\a1 a2 -> ap' (hf a1 a2) (ha a1 a2))--instance (Apply f) => Apply (BinaryFunctionT f a) where-  (<.>) = apBFT (<.>)---- |--- >>> let BinaryFunctionT f = pure 42 :: BinaryFunctionT [] Int Int--- >>> f 1 2--- [42]------ >>> let BinaryFunctionT f = (BinaryFunctionT (\x y -> [(*x), (*y)]) :: BinaryFunctionT [] Int (Int -> Int)) <*> BinaryFunctionT (\x y -> [x + y, x * y])--- >>> f 3 5--- [24,45,40,75]-instance (Applicative f) => Applicative (BinaryFunctionT f a) where-  pure b = BinaryFunctionT (\_ _ -> pure b)-  (<*>) = apBFT (<*>)---- |--- >>> import Data.Functor.Bind ((>>-))--- >>> let BinaryFunctionT f = BinaryFunctionT (\x y -> [x + y, x * y]) >>- (\b -> BinaryFunctionT (\x y -> [b + x, b + y])) :: BinaryFunctionT [] Int Int--- >>> f 3 5--- [11,13,18,20]-bindBFT :: (f b -> (b -> f c) -> f c) -> BinaryFunctionT f a b -> (b -> BinaryFunctionT f a c) -> BinaryFunctionT f a c-bindBFT bnd (BinaryFunctionT h) k = BinaryFunctionT (\a1 a2 -> bnd (h a1 a2) (\b -> view _Wrapped (k b) a1 a2))--instance (Bind f) => Bind (BinaryFunctionT f a) where-  (>>-) = bindBFT (>>-)---- |--- >>> let BinaryFunctionT f = BinaryFunctionT (\x y -> [x + y, x * y]) >>= (\b -> BinaryFunctionT (\x y -> [b + x, b + y])) :: BinaryFunctionT [] Int Int--- >>> f 3 5--- [11,13,18,20]------ >>> let BinaryFunctionT f = return 42 :: BinaryFunctionT [] Int Int--- >>> f 1 2--- [42]-instance (Monad f) => Monad (BinaryFunctionT f a) where-  (>>=) = bindBFT (>>=)---- |--- >>> import Data.Profunctor (dimap, lmap, rmap)--- >>> let BinaryFunctionT f = dimap (+1) (*2) (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f 3 5--- [20]------ >>> import Data.Profunctor (lmap)--- >>> let BinaryFunctionT f = lmap (*10) (BinaryFunctionT (\x y -> [x, y]) :: BinaryFunctionT [] Int Int)--- >>> f 3 5--- [30,50]------ >>> import Data.Profunctor (rmap)--- >>> let BinaryFunctionT f = rmap show (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f 3 5--- ["8"]-instance (Functor f) => Profunctor (BinaryFunctionT f) where-  dimap f g = over _Wrapped (\h a1 a2 -> fmap g (h (f a1) (f a2)))-  lmap f = over _Wrapped (\h a1 a2 -> h (f a1) (f a2))-  rmap g = over _Wrapped (\h a1 a2 -> fmap g (h a1 a2))---- |--- >>> import Data.Profunctor (Strong(..))--- >>> let BinaryFunctionT f = first' (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f (1, "hello") (2, "world")--- [(3,"hello")]------ >>> import Data.Profunctor (Strong(..))--- >>> let BinaryFunctionT f = second' (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f ("hello", 1) ("world", 2)--- [("hello",3)]-instance (Functor f) => Strong (BinaryFunctionT f) where-  first' = over _Wrapped (\h (a1, c) (a2, _) -> fmap (,c) (h a1 a2))-  second' = over _Wrapped (\h (c, a1) (_, a2) -> fmap (c,) (h a1 a2))---- |--- >>> import Data.Profunctor (Choice(..))--- >>> let BinaryFunctionT f = left' (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f (Left 1) (Left 2)--- [Left 3]--- >>> f (Left 1) (Right "hi")--- [Right "hi"]--- >>> f (Right "hi") (Left 2)--- [Right "hi"]--- >>> f (Right "a") (Right "b")--- [Right "a"]------ >>> import Data.Profunctor (Choice(..))--- >>> let BinaryFunctionT f = right' (BinaryFunctionT (\x y -> [x + y]) :: BinaryFunctionT [] Int Int)--- >>> f (Right 1) (Right 2)--- [Right 3]--- >>> f (Left "hi") (Right 2)--- [Left "hi"]-instance (Applicative f) => Choice (BinaryFunctionT f) where-  left' = over _Wrapped $ \h ea1 ea2 -> case (ea1, ea2) of-    (Left a1, Left a2) -> fmap Left (h a1 a2)-    (Right c, _) -> pure (Right c)-    (_, Right c) -> pure (Right c)-  right' = over _Wrapped $ \h ea1 ea2 -> case (ea1, ea2) of-    (Right a1, Right a2) -> fmap Right (h a1 a2)-    (Left c, _) -> pure (Left c)-    (_, Left c) -> pure (Left c)---- |--- >>> import Control.Monad.Fix (mfix)--- >>> let BinaryFunctionT f = mfix (\x -> BinaryFunctionT (\a _ -> [const 42 x + a])) :: BinaryFunctionT [] Int Int--- >>> f 1 2--- [43]-instance (MonadFix f) => MonadFix (BinaryFunctionT f a) where-  mfix g = BinaryFunctionT (\a1 a2 -> mfix (\b -> view _Wrapped (g b) a1 a2))---- |--- >>> import Control.Selective (select)--- >>> let BinaryFunctionT f = select (BinaryFunctionT (\_ _ -> [Left 1, Right 2]) :: BinaryFunctionT [] Int (Either Int Int)) (BinaryFunctionT (\_ _ -> [(+10)]))--- >>> f 0 0--- [11,2]-instance (Monad f) => Selective (BinaryFunctionT f a) where-  select = selectM---- |--- >>> import Control.Monad.Zip (mzip)--- >>> let BinaryFunctionT f = mzip (BinaryFunctionT (\x y -> [x + y, x * y]) :: BinaryFunctionT [] Int Int) (BinaryFunctionT (\x y -> [x - y]))--- >>> f 5 3--- [(8,2)]-instance (MonadZip f) => MonadZip (BinaryFunctionT f a) where-  mzipWith g (BinaryFunctionT h1) (BinaryFunctionT h2) = BinaryFunctionT (\a1 a2 -> mzipWith g (h1 a1 a2) (h2 a1 a2))---- |--- >>> let BinaryFunctionT f = liftIO (putStrLn "hello") :: BinaryFunctionT IO Int ()--- >>> f 1 2--- hello-instance (MonadIO f) => MonadIO (BinaryFunctionT f a) where-  liftIO io = BinaryFunctionT (\_ _ -> liftIO io)---- |--- >>> import Data.Functor.Alt ((<!>))--- >>> let BinaryFunctionT f = (BinaryFunctionT (\_ _ -> Nothing) :: BinaryFunctionT Maybe Int Int) <!> BinaryFunctionT (\x y -> Just (x + y))--- >>> f 3 5--- Just 8-instance (Alt f) => Alt (BinaryFunctionT f a) where-  BinaryFunctionT h1 <!> BinaryFunctionT h2 = BinaryFunctionT (\a1 a2 -> h1 a1 a2 <!> h2 a1 a2)---- |--- >>> import Data.Functor.Plus (zero)--- >>> let BinaryFunctionT f = zero :: BinaryFunctionT [] Int Int--- >>> f 1 2--- []-instance (Plus f) => Plus (BinaryFunctionT f a) where-  zero = BinaryFunctionT (\_ _ -> zero)---- |--- >>> import Control.Applicative (empty, (<|>))--- >>> let BinaryFunctionT f = (BinaryFunctionT (\_ _ -> Nothing) :: BinaryFunctionT Maybe Int Int) <|> BinaryFunctionT (\x y -> Just (x + y))--- >>> f 3 5--- Just 8------ >>> import Control.Applicative (empty)--- >>> let BinaryFunctionT f = empty :: BinaryFunctionT [] Int Int--- >>> f 1 2--- []-instance (Alternative f) => Alternative (BinaryFunctionT f a) where-  empty = BinaryFunctionT (\_ _ -> empty)-  BinaryFunctionT h1 <|> BinaryFunctionT h2 = BinaryFunctionT (\a1 a2 -> h1 a1 a2 <|> h2 a1 a2)---- |--- >>> let BinaryFunctionT f = runSemigroup semigroupBinaryFunctionT (BinaryFunctionT (\_ _ -> [1, 2]) :: BinaryFunctionT [] Int Int) (BinaryFunctionT (\_ _ -> [10, 20])) in f 0 0--- [1,2,10,20]-semigroupBinaryFunctionT :: (Prelude.Semigroup (f b)) => Semigroup' (BinaryFunctionT f a b)-semigroupBinaryFunctionT = review applySemigroup (\(BinaryFunctionT h1) (BinaryFunctionT h2) -> BinaryFunctionT (\a1 a2 -> h1 a1 a2 <> h2 a1 a2))---- |--- >>> let BinaryFunctionT f = BinaryFunctionT (\_ _ -> [1, 2]) <> (BinaryFunctionT (\_ _ -> [3, 4]) :: BinaryFunctionT [] Int Int)--- >>> f 0 0--- [1,2,3,4]-instance (Prelude.Semigroup (f b)) => Prelude.Semigroup (BinaryFunctionT f a b) where-  (<>) = runSemigroup semigroupBinaryFunctionT---- |--- >>> let BinaryFunctionT f = mempty :: BinaryFunctionT [] Int Int--- >>> f 1 2--- []-instance (Prelude.Monoid (f b)) => Prelude.Monoid (BinaryFunctionT f a b) where-  mempty = BinaryFunctionT (\_ _ -> mempty)---- |--- >>> import Data.Distributive (distribute)--- >>> import Data.Functor.Identity (Identity(..))--- >>> let BinaryFunctionT f = distribute [BinaryFunctionT (\x y -> Identity (x + y)), BinaryFunctionT (\x y -> Identity (x * y))] :: BinaryFunctionT Identity Int [Int]--- >>> f 3 5--- Identity [8,15]-instance (Distributive f) => Distributive (BinaryFunctionT f a) where-  distribute gs = BinaryFunctionT (\a1 a2 -> distribute (fmap (\(BinaryFunctionT h) -> h a1 a2) gs))---- |--- >>> import Data.Profunctor.Closed (Closed(..))--- >>> import Data.Functor.Identity (Identity(..))--- >>> let BinaryFunctionT f = closed (BinaryFunctionT (\x y -> Identity (x + y)) :: BinaryFunctionT Identity Int Int)--- >>> runIdentity (f (*2) (*3)) 10--- 50-instance (Distributive f) => Closed (BinaryFunctionT f) where-  closed (BinaryFunctionT h) = BinaryFunctionT (\xa1 xa2 -> distribute (\x -> h (xa1 x) (xa2 x)))
+ src/Data/Valuation/CovariantFunctor.hs view
@@ -0,0 +1,212 @@+{-# LANGUAGE RankNTypes #-}+{-# OPTIONS_GHC -Wall -Werror #-}++-- | A reified covariant functor: a covariant mapping from one category to another,+-- wrapping @forall a b. cat a b -> cat' (f a) (f b)@.+--+-- 'CovariantFunctor' @cat cat' f@ reifies the action of a covariant functor on+-- a type constructor @f@, generalised over a source category @cat@ and a+-- target category @cat'@. When both are @(->)@, this specialises to+-- 'CovariantFunctor'' @f@ wrapping @forall a b. (a -> b) -> f a -> f b@, which is+-- exactly 'fmap'.+--+-- Unlike 'Functor' which is a type class (one instance per type), this is a+-- value — and it is generalised over the source and target categories.+--+-- @+-- newtype 'CovariantFunctor' cat cat' f = 'CovariantFunctor' (forall a b. cat a b -> cat' (f a) (f b))+-- type 'CovariantFunctor'' f = 'CovariantFunctor' (->) (->) f+-- @+module Data.Valuation.CovariantFunctor+  ( CovariantFunctor (..),+    CovariantFunctor',++    -- * combinators+    runCovariantFunctor,+    composeFunctor,+    fmapCovariantFunctor,++    -- * covariant functor values+    identityCovariantFunctor,+    maybeCovariantFunctor,+    listCovariantFunctor,+    proxyCovariantFunctor,+    constCovariantFunctor,++    -- * laws+    lawCovariantFunctorIdentity,+    lawCovariantFunctorComposition,+  )+where++import Data.Functor.Compose (Compose (..))+import Data.Functor.Const (Const (..))+import Data.Functor.Identity (Identity (..))+import Data.Profunctor (Profunctor (dimap))+import Data.Proxy (Proxy)++-- $setup+-- >>> :set -Wno-name-shadowing -Wno-type-defaults+-- >>> import Data.Functor.Const (Const(..))+-- >>> import Data.Functor.Identity (Identity(..))+-- >>> import Data.Proxy (Proxy(..))++-- |+-- >>> runCovariantFunctor listCovariantFunctor (+1) [1,2,3]+-- [2,3,4]+--+-- >>> runCovariantFunctor maybeCovariantFunctor (*2) (Just 5)+-- Just 10+newtype CovariantFunctor cat cat' f = CovariantFunctor (forall a b. cat a b -> cat' (f a) (f b))++-- | A 'CovariantFunctor' specialised to @(->)@ for both categories.+-- Wraps @forall a b. (a -> b) -> f a -> f b@, equivalent to 'fmap'.+type CovariantFunctor' f = CovariantFunctor (->) (->) f++-- | Unwrap a 'CovariantFunctor' to its underlying natural transformation.+--+-- >>> runCovariantFunctor identityCovariantFunctor (+1) (Identity 3)+-- Identity 4+--+-- >>> runCovariantFunctor maybeCovariantFunctor show (Just 42)+-- Just "42"+-- >>> runCovariantFunctor maybeCovariantFunctor show Nothing+-- Nothing+--+-- >>> runCovariantFunctor listCovariantFunctor (*2) [1,2,3]+-- [2,4,6]+-- >>> runCovariantFunctor listCovariantFunctor (*2) []+-- []+runCovariantFunctor :: CovariantFunctor cat cat' f -> cat a b -> cat' (f a) (f b)+runCovariantFunctor (CovariantFunctor f) = f++-- | Compose two covariant functors.+-- The result is covariant (covariant ∘ covariant = covariant).+--+-- Given @f@ covariant from @cat@ to @cat'@ and @g@ covariant from @cat'@ to @cat''@,+-- @g ∘ f@ is covariant from @cat@ to @cat''@ acting on @'Compose' g f@.+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> let p = composeFunctor maybeCovariantFunctor listCovariantFunctor+-- >>> runCovariantFunctor p (+1) (Compose [Just 1, Nothing, Just 3])+-- Compose [Just 2,Nothing,Just 4]+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> let p = composeFunctor listCovariantFunctor maybeCovariantFunctor+-- >>> runCovariantFunctor p (+1) (Compose (Just [1,2,3]))+-- Compose (Just [2,3,4])+-- >>> runCovariantFunctor p (+1) (Compose Nothing :: Compose Maybe [] Int)+-- Compose Nothing+composeFunctor ::+  (Profunctor cat'') =>+  CovariantFunctor cat cat' f ->+  CovariantFunctor cat' cat'' g ->+  CovariantFunctor cat cat'' (Compose g f)+composeFunctor (CovariantFunctor f) (CovariantFunctor g) =+  CovariantFunctor (dimap getCompose Compose . g . f)++-- | The canonical 'CovariantFunctor'' for any 'Functor',+-- using 'fmap'.+--+-- >>> runCovariantFunctor fmapCovariantFunctor (+1) [1,2,3]+-- [2,3,4]+-- >>> runCovariantFunctor fmapCovariantFunctor not (Just True)+-- Just False+fmapCovariantFunctor :: (Functor f) => CovariantFunctor' f+fmapCovariantFunctor = CovariantFunctor fmap++-- | 'CovariantFunctor'' on 'Identity': maps the wrapped value.+--+-- >>> runCovariantFunctor identityCovariantFunctor (+1) (Identity 3)+-- Identity 4+-- >>> runCovariantFunctor identityCovariantFunctor show (Identity 42)+-- Identity "42"+identityCovariantFunctor :: CovariantFunctor' Identity+identityCovariantFunctor = CovariantFunctor fmap++-- | 'CovariantFunctor'' on 'Maybe': maps over the contained value if present.+--+-- >>> runCovariantFunctor maybeCovariantFunctor (+1) (Just 3)+-- Just 4+-- >>> runCovariantFunctor maybeCovariantFunctor (+1) Nothing+-- Nothing+--+-- >>> runCovariantFunctor maybeCovariantFunctor show (Just 42)+-- Just "42"+maybeCovariantFunctor :: CovariantFunctor' Maybe+maybeCovariantFunctor = CovariantFunctor fmap++-- | 'CovariantFunctor'' on @[]@: maps over each element.+--+-- >>> runCovariantFunctor listCovariantFunctor (+1) [1,2,3]+-- [2,3,4]+-- >>> runCovariantFunctor listCovariantFunctor (*2) []+-- []+--+-- >>> runCovariantFunctor listCovariantFunctor show [1,2,3]+-- ["1","2","3"]+listCovariantFunctor :: CovariantFunctor' []+listCovariantFunctor = CovariantFunctor fmap++-- | 'CovariantFunctor'' on 'Proxy': trivially maps the phantom type parameter.+--+-- >>> runCovariantFunctor proxyCovariantFunctor not (Proxy :: Proxy Bool)+-- Proxy+--+-- >>> runCovariantFunctor proxyCovariantFunctor show (Proxy :: Proxy Int)+-- Proxy+proxyCovariantFunctor :: CovariantFunctor' Proxy+proxyCovariantFunctor = CovariantFunctor fmap++-- | 'CovariantFunctor'' on @'Const' r@: trivially maps the phantom second parameter.+-- The constant value is preserved.+--+-- >>> runCovariantFunctor constCovariantFunctor not (Const 42 :: Const Int Bool)+-- Const 42+--+-- >>> runCovariantFunctor constCovariantFunctor show (Const "hello" :: Const String Int)+-- Const "hello"+constCovariantFunctor :: CovariantFunctor' (Const r)+constCovariantFunctor = CovariantFunctor fmap++-- | The identity law for a 'CovariantFunctor'': mapping the identity morphism+-- must be the identity on @f a@.+--+-- @+-- 'runCovariantFunctor' p 'id' x == x+-- @+--+-- >>> lawCovariantFunctorIdentity identityCovariantFunctor (Identity 42)+-- True+-- >>> lawCovariantFunctorIdentity maybeCovariantFunctor (Just 42 :: Maybe Int)+-- True+-- >>> lawCovariantFunctorIdentity listCovariantFunctor [1,2,3 :: Int]+-- True+-- >>> lawCovariantFunctorIdentity proxyCovariantFunctor (Proxy :: Proxy Int)+-- True+-- >>> lawCovariantFunctorIdentity constCovariantFunctor (Const 42 :: Const Int Bool)+-- True+lawCovariantFunctorIdentity :: (Eq (f a)) => CovariantFunctor' f -> f a -> Bool+lawCovariantFunctorIdentity p x =+  runCovariantFunctor p id x == x++-- | The composition law for a 'CovariantFunctor'': mapping a composition must+-- equal composing the individual mappings.+--+-- @+-- 'runCovariantFunctor' p (g '.' f) x == 'runCovariantFunctor' p g ('runCovariantFunctor' p f x)+-- @+--+-- >>> lawCovariantFunctorComposition identityCovariantFunctor (+1) (*2) (Identity 3)+-- True+-- >>> lawCovariantFunctorComposition maybeCovariantFunctor (+1) (*2) (Just 3 :: Maybe Int)+-- True+-- >>> lawCovariantFunctorComposition listCovariantFunctor (+1) (*2) [1,2,3 :: Int]+-- True+-- >>> lawCovariantFunctorComposition proxyCovariantFunctor not (&&True) (Proxy :: Proxy Bool)+-- True+-- >>> lawCovariantFunctorComposition constCovariantFunctor (+1) (*2) (Const "hello" :: Const String Int)+-- True+lawCovariantFunctorComposition :: (Eq (f c)) => CovariantFunctor' f -> (b -> c) -> (a -> b) -> f a -> Bool+lawCovariantFunctorComposition p g f x =+  runCovariantFunctor p (g . f) x == runCovariantFunctor p g (runCovariantFunctor p f x)
src/Data/Valuation/DomainLattice.hs view
@@ -14,6 +14,7 @@ module Data.Valuation.DomainLattice   ( DomainLattice (..),     DomainLattice',+    DomainLattice'',     HasDomainLattice (..),     AsDomainLattice (..),     runDomainJoin,@@ -75,11 +76,14 @@       -- | meet (/\ / infimum)       (Semigroup p sg)       -- | partial order-      (PartialOrder o)+      (PartialOrder p o) -type DomainLattice' x =-  DomainLattice (->) x x+type DomainLattice' sg o =+  DomainLattice (->) sg o +type DomainLattice'' x =+  DomainLattice' x x+ -- | Classy lens for types that contain a 'DomainLattice'. class HasDomainLattice c p sg o | c -> p sg o where   domainLattice :: Lens' c (DomainLattice p sg o)@@ -100,7 +104,7 @@ instance AsDomainLattice (DomainLattice p sg o) p sg o where   _DomainLattice = id -instance HasPartialOrder (DomainLattice p sg o) o where+instance HasPartialOrder (DomainLattice p sg o) p o where   partialOrder f (DomainLattice j m o) = fmap (DomainLattice j m) (f o)  -- | Apply the domain join (\/): the supremum of two domains.@@ -128,9 +132,9 @@ -- >>> runDomainCompare (setDomainLattice :: DomainLattice (->) (Set Int) (Set Int)) (Set.fromList [1,2]) (Set.fromList [2,3]) -- Nothing {-# SPECIALIZE runDomainCompare ::-  DomainLattice p sg o -> o -> o -> Maybe Ordering+  DomainLattice (->) sg o -> o -> o -> Maybe Ordering   #-}-runDomainCompare :: (HasPartialOrder lat p) => lat -> p -> p -> Maybe Ordering+runDomainCompare :: (HasPartialOrder lat (->) o) => lat -> o -> o -> Maybe Ordering runDomainCompare = runPartialOrder . view partialOrder  -- | Test the domain partial order: @runDomainLeq lat d1 d2@ is 'True' iff @d1 <= d2@.@@ -142,9 +146,9 @@ -- >>> runDomainLeq (setDomainLattice :: DomainLattice (->) (Set Int) (Set Int)) (Set.fromList [1,2]) (Set.fromList [2,3]) -- False {-# SPECIALIZE runDomainLeq ::-  DomainLattice p sg o -> o -> o -> Bool+  DomainLattice (->) sg o -> o -> o -> Bool   #-}-runDomainLeq :: (HasPartialOrder lat p) => lat -> p -> p -> Bool+runDomainLeq :: (HasPartialOrder lat (->) o) => lat -> o -> o -> Bool runDomainLeq = partialOrderLeq . view partialOrder  -- | The canonical 'DomainLattice' for 'Set', with union as join,@@ -160,7 +164,7 @@ -- True -- >>> runDomainCompare lat (Set.fromList ["x","y"]) (Set.fromList ["y","z"]) -- Nothing-setDomainLattice :: (Ord a) => DomainLattice' (Set a)+setDomainLattice :: (Ord a) => DomainLattice'' (Set a) setDomainLattice =   DomainLattice     (review applySemigroup Set.union)@@ -171,7 +175,7 @@ -- >>> import qualified Data.Set as Set -- >>> lawJoinAssociative (setDomainLattice :: DomainLattice (->) (Set Int) (Set Int)) (Set.fromList [1,2]) (Set.fromList [2,3]) (Set.fromList [3,4]) -- True-lawJoinAssociative :: (Eq sg) => DomainLattice (->) sg o -> sg -> sg -> sg -> Bool+lawJoinAssociative :: (Eq sg) => DomainLattice' sg o -> sg -> sg -> sg -> Bool lawJoinAssociative lat a b c =   let j = runDomainJoin lat    in j (j a b) c == j a (j b c)@@ -180,7 +184,7 @@ -- >>> import qualified Data.Set as Set -- >>> lawMeetAssociative (setDomainLattice :: DomainLattice (->) (Set Int) (Set Int)) (Set.fromList [1,2]) (Set.fromList [2,3]) (Set.fromList [3,4]) -- True-lawMeetAssociative :: (Eq sg) => DomainLattice (->) sg o -> sg -> sg -> sg -> Bool+lawMeetAssociative :: (Eq sg) => DomainLattice' sg o -> sg -> sg -> sg -> Bool lawMeetAssociative lat a b c =   let m = runDomainMeet lat    in m (m a b) c == m a (m b c)@@ -244,6 +248,6 @@ -- True -- >>> lawLeqFromJoin (setDomainLattice :: DomainLattice (->) (Set Int) (Set Int)) (Set.fromList [1,3]) (Set.fromList [1,2]) -- True-lawLeqFromJoin :: (Eq d) => DomainLattice' d -> d -> d -> Bool+lawLeqFromJoin :: (Eq d) => DomainLattice'' d -> d -> d -> Bool lawLeqFromJoin lat a b =   runDomainLeq lat a b == (runDomainJoin lat a b == b)
src/Data/Valuation/PartialOrder.hs view
@@ -1,10 +1,15 @@+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -Wall -Werror #-} --- | A partial order on a type, wrapping @a -> a -> 'Maybe' 'Ordering'@.+-- | A partial order on a type, generalised over a 'Profunctor' @p@,+-- wrapping @p a (p a ('Maybe' 'Ordering'))@.+-- When @p ~ (->)@, this specialises to @a -> a -> 'Maybe' 'Ordering'@+-- (see 'PartialOrder''). -- -- This is the partial order analogue of 'Data.Functor.Contravariant.Comparison' -- (which represents total orders via @a -> a -> 'Ordering'@).@@ -18,42 +23,44 @@ -- @ module Data.Valuation.PartialOrder   ( PartialOrder (..),+    PartialOrder',      -- * optics     HasPartialOrder (..),     AsPartialOrder (..),-    isBinaryFunctionT,      -- * combinators     semigroupPartialOrder,     runPartialOrder,     partialOrderLeq,     totalOrder,+    comparisonTotalOrder,+    fromEquivalence,     fromLeq,   ) where  import Control.Lens-  ( Iso,-    Lens',+  ( Lens',     Prism',     Rewrapped,     Wrapped (..),-    from,     iso,     review,-    _Wrapped,   )-import Data.Functor.Contravariant (Contravariant (..))+import Data.Functor.Apply (Apply, liftF2)+import Data.Functor.Contravariant+  ( Comparison (Comparison),+    Contravariant (contramap),+    Equivalence (Equivalence),+  ) import Data.Functor.Contravariant.Conclude (Conclude (..)) import Data.Functor.Contravariant.Decide (Decide (..)) import Data.Functor.Contravariant.Divise (Divise (..)) import Data.Functor.Contravariant.Divisible (Decidable (..), Divisible (..))-import Data.Valuation.BinaryFunction-  ( AsBinaryFunctionT (..),-    BinaryFunctionT,-    HasBinaryFunctionT (..),-  )+import Data.Profunctor (Profunctor (..))+import qualified Data.Profunctor.Rep as Pro+import Data.Profunctor.Sieve (Sieve (..)) import Data.Valuation.Semigroup   ( Semigroup',     applySemigroup,@@ -68,74 +75,69 @@ -- >>> import Data.Void (Void)  -- |--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 1 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 1 2 -- Just LT--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 2 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 2 2 -- Just EQ--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 3 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 3 2 -- Just GT -- -- >>> import qualified Data.Set as Set -- >>> runPartialOrder (fromLeq Set.isSubsetOf) (Set.fromList [1,2]) (Set.fromList [2,3 :: Int]) -- Nothing-newtype PartialOrder a-  = PartialOrder (a -> a -> Maybe Ordering)+newtype PartialOrder p a+  = PartialOrder (p a (p a (Maybe Ordering))) -instance (PartialOrder a ~ t) => Rewrapped (PartialOrder a') t+type PartialOrder' a =+  PartialOrder (->) a -instance Wrapped (PartialOrder a) where-  type Unwrapped (PartialOrder a) = a -> a -> Maybe Ordering+instance (PartialOrder' a ~ t) => Rewrapped (PartialOrder' a') t++instance Wrapped (PartialOrder' a) where+  type Unwrapped (PartialOrder' a) = a -> a -> Maybe Ordering   _Wrapped' = iso (\(PartialOrder x) -> x) PartialOrder  -- | Classy lens for types that contain a 'PartialOrder'.-class HasPartialOrder c a | c -> a where-  partialOrder :: Lens' c (PartialOrder a)+class HasPartialOrder c p a | c -> p a where+  partialOrder :: Lens' c (PartialOrder p a) -instance HasPartialOrder (PartialOrder a) a where+instance HasPartialOrder (PartialOrder p a) p a where   partialOrder = id  -- | Classy prism for types that can be constructed from a 'PartialOrder'.-class AsPartialOrder c a | c -> a where-  _PartialOrder :: Prism' c (PartialOrder a)+class AsPartialOrder c p a | c -> p a where+  _PartialOrder :: Prism' c (PartialOrder p a) -instance AsPartialOrder (PartialOrder a) a where+instance AsPartialOrder (PartialOrder p a) p a where   _PartialOrder = id -instance HasBinaryFunctionT (PartialOrder a) Maybe a Ordering where-  binaryFunctionT = isBinaryFunctionT--instance AsBinaryFunctionT (PartialOrder a) Maybe a Ordering where-  _BinaryFunctionT = isBinaryFunctionT--isBinaryFunctionT :: Iso (PartialOrder a) (PartialOrder a') (BinaryFunctionT Maybe a Ordering) (BinaryFunctionT Maybe a' Ordering)-isBinaryFunctionT = _Wrapped . from _Wrapped---- | Apply the partial order comparison.+-- | Unwrap the partial order to its underlying profunctor value.+-- For @p ~ (->)@, this gives @a -> a -> 'Maybe' 'Ordering'@. ----- >>> runPartialOrder (totalOrder :: PartialOrder Int) 1 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 1 2 -- Just LT--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 2 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 2 2 -- Just EQ--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 3 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 3 2 -- Just GT-runPartialOrder :: PartialOrder a -> a -> a -> Maybe Ordering+runPartialOrder :: PartialOrder p a -> p a (p a (Maybe Ordering)) runPartialOrder (PartialOrder f) = f  -- | Test whether @a <= b@ in the partial order. -- Returns 'True' iff the comparison yields 'Just' 'LT' or 'Just' 'EQ'. -- Returns 'False' for incomparable elements. ----- >>> partialOrderLeq (totalOrder :: PartialOrder Int) 1 2+-- >>> partialOrderLeq (totalOrder :: PartialOrder' Int) 1 2 -- True--- >>> partialOrderLeq (totalOrder :: PartialOrder Int) 2 2+-- >>> partialOrderLeq (totalOrder :: PartialOrder' Int) 2 2 -- True--- >>> partialOrderLeq (totalOrder :: PartialOrder Int) 3 2+-- >>> partialOrderLeq (totalOrder :: PartialOrder' Int) 3 2 -- False -- -- >>> import qualified Data.Set as Set -- >>> partialOrderLeq (fromLeq Set.isSubsetOf) (Set.fromList [1,2]) (Set.fromList [2,3 :: Int]) -- False-partialOrderLeq :: PartialOrder a -> a -> a -> Bool+partialOrderLeq :: PartialOrder' a -> a -> a -> Bool partialOrderLeq po a b = case runPartialOrder po a b of   Just LT -> True   Just EQ -> True@@ -144,15 +146,42 @@ -- | Construct a 'PartialOrder' from a total order ('Ord' instance). -- The result never yields 'Nothing' since all elements are comparable. ----- >>> runPartialOrder (totalOrder :: PartialOrder Int) 1 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 1 2 -- Just LT--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 2 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 2 2 -- Just EQ--- >>> runPartialOrder (totalOrder :: PartialOrder Int) 3 2+-- >>> runPartialOrder (totalOrder :: PartialOrder' Int) 3 2 -- Just GT-totalOrder :: (Ord a) => PartialOrder a+totalOrder :: (Ord a) => PartialOrder' a totalOrder = PartialOrder (\a b -> Just (compare a b)) +-- | Lift a 'Comparison' (a reified total order) into a 'PartialOrder''.+-- Since a total order has no incomparable elements, the result+-- always yields @'Just' o@ for some 'Ordering' @o@, never 'Nothing'.+--+-- >>> import Data.Functor.Contravariant (Comparison(..))+-- >>> runPartialOrder (comparisonTotalOrder (Comparison compare)) (1 :: Int) 2+-- Just LT+-- >>> runPartialOrder (comparisonTotalOrder (Comparison compare)) (2 :: Int) 2+-- Just EQ+-- >>> runPartialOrder (comparisonTotalOrder (Comparison compare)) (3 :: Int) 2+-- Just GT+--+-- >>> import Data.Functor.Contravariant (Comparison(..), contramap)+-- >>> runPartialOrder (comparisonTotalOrder (contramap negate (Comparison compare))) (1 :: Int) 2+-- Just GT+--+-- >>> import Data.Functor.Contravariant (Comparison(..))+-- >>> partialOrderLeq (comparisonTotalOrder (Comparison compare)) (1 :: Int) 2+-- True+-- >>> partialOrderLeq (comparisonTotalOrder (Comparison compare)) (2 :: Int) 1+-- False+comparisonTotalOrder :: Comparison a -> PartialOrder' a+comparisonTotalOrder (Comparison cmp) = PartialOrder (\a1 a2 -> Just (cmp a1 a2))++fromEquivalence :: (Bool -> Maybe Ordering) -> Equivalence a -> PartialOrder' a+fromEquivalence k (Equivalence p) = PartialOrder (\a1 a2 -> k (p a1 a2))+ -- | Construct a 'PartialOrder' from a less-than-or-equal predicate. -- -- The predicate should satisfy the partial order laws@@ -160,7 +189,7 @@ -- Elements where neither @leq a b@ nor @leq b a@ holds are incomparable ('Nothing'). -- -- >>> import qualified Data.Set as Set--- >>> let po = fromLeq Set.isSubsetOf :: PartialOrder (Set.Set Int)+-- >>> let po = fromLeq Set.isSubsetOf :: PartialOrder' (Set.Set Int) -- >>> runPartialOrder po (Set.fromList [1]) (Set.fromList [1,2]) -- Just LT -- >>> runPartialOrder po (Set.fromList [1,2]) (Set.fromList [1,2])@@ -169,7 +198,7 @@ -- Just GT -- >>> runPartialOrder po (Set.fromList [1,2]) (Set.fromList [2,3]) -- Nothing-fromLeq :: (a -> a -> Bool) -> PartialOrder a+fromLeq :: (a -> a -> Bool) -> PartialOrder' a fromLeq leq = PartialOrder $ \a b ->   case (leq a b, leq b a) of     (True, True) -> Just EQ@@ -179,51 +208,56 @@  -- | -- >>> import Data.Functor.Contravariant (contramap)--- >>> runPartialOrder (contramap negate (totalOrder :: PartialOrder Int)) 1 2+-- >>> runPartialOrder (contramap negate (totalOrder :: PartialOrder' Int)) 1 2 -- Just GT--- >>> runPartialOrder (contramap negate (totalOrder :: PartialOrder Int)) 2 1+-- >>> runPartialOrder (contramap negate (totalOrder :: PartialOrder' Int)) 2 1 -- Just LT-instance Contravariant PartialOrder where-  contramap f (PartialOrder g) = PartialOrder (\a b -> g (f a) (f b))+instance (Profunctor p) => Contravariant (PartialOrder p) where+  contramap f (PartialOrder g) = PartialOrder (dimap f (lmap f) g)  -- | Lexicographic composition as a first-class 'Semigroup': compare by the -- first partial order; if equal ('Just' 'EQ'), compare by the second. -- If the first yields 'Nothing' (incomparable), the result is 'Nothing'. ----- >>> let po = totalOrder :: PartialOrder Int+-- >>> let po = totalOrder :: PartialOrder' Int -- >>> runPartialOrder (runSemigroup semigroupPartialOrder po po) 1 2 -- Just LT -- >>> runPartialOrder (runSemigroup semigroupPartialOrder po po) 2 2 -- Just EQ-semigroupPartialOrder :: Semigroup' (PartialOrder a)-semigroupPartialOrder = review applySemigroup $ \(PartialOrder f) (PartialOrder g) -> PartialOrder $ \a b ->-  case f a b of-    Just EQ -> g a b-    r -> r+semigroupPartialOrder :: (Pro.Representable p, Apply (Pro.Rep p)) => Semigroup' (PartialOrder p a)+semigroupPartialOrder = review applySemigroup $ \(PartialOrder pf) (PartialOrder pg) ->+  PartialOrder $ Pro.tabulate $ \a ->+    liftF2+      ( \innerF innerG -> Pro.tabulate $ \b ->+          liftF2 (\r1 r2 -> case r1 of Just EQ -> r2; _ -> r1) (sieve innerF b) (sieve innerG b)+      )+      (sieve pf a)+      (sieve pg a)+{-# SPECIALIZE semigroupPartialOrder :: Semigroup' (PartialOrder' a) #-}  -- |--- >>> let po = totalOrder :: PartialOrder Int+-- >>> let po = totalOrder :: PartialOrder' Int -- >>> runPartialOrder (po <> po) 1 2 -- Just LT -- >>> runPartialOrder (po <> po) 2 2 -- Just EQ-instance Prelude.Semigroup (PartialOrder a) where+instance (Pro.Representable p, Apply (Pro.Rep p)) => Prelude.Semigroup (PartialOrder p a) where   (<>) = runSemigroup semigroupPartialOrder  -- | The trivial partial order where all elements are equal. ----- >>> runPartialOrder (mempty :: PartialOrder Int) 1 2+-- >>> runPartialOrder (mempty :: PartialOrder' Int) 1 2 -- Just EQ--- >>> runPartialOrder (mempty :: PartialOrder Int) 42 99+-- >>> runPartialOrder (mempty :: PartialOrder' Int) 42 99 -- Just EQ-instance Monoid (PartialOrder a) where-  mempty = PartialOrder (\_ _ -> Just EQ)+instance (Pro.Representable p, Apply (Pro.Rep p), Applicative (Pro.Rep p)) => Monoid (PartialOrder p a) where+  mempty = PartialOrder (Pro.tabulate (\_ -> pure (Pro.tabulate (\_ -> pure (Just EQ)))))  -- | Lexicographic product: split @a@ into @(b, c)@, compare by @b@ first, -- if equal then compare by @c@. @conquer@ treats all elements as equal. -- -- >>> import Data.Functor.Contravariant.Divisible (divide, conquer)--- >>> let po = divide id (totalOrder :: PartialOrder Int) (totalOrder :: PartialOrder Int)+-- >>> let po = divide id (totalOrder :: PartialOrder' Int) (totalOrder :: PartialOrder' Int) -- >>> runPartialOrder po (1, 2) (1, 3) -- Just LT -- >>> runPartialOrder po (1, 2) (2, 1)@@ -232,9 +266,9 @@ -- Just EQ -- -- >>> import Data.Functor.Contravariant.Divisible (conquer)--- >>> runPartialOrder (conquer :: PartialOrder Int) 1 2+-- >>> runPartialOrder (conquer :: PartialOrder' Int) 1 2 -- Just EQ-instance Divisible PartialOrder where+instance (Pro.Representable p, Apply (Pro.Rep p), Applicative (Pro.Rep p)) => Divisible (PartialOrder p) where   conquer = mempty   divide f pb pc = contramap (fst . f) pb <> contramap (snd . f) pc @@ -244,7 +278,7 @@ -- -- >>> import Data.Functor.Contravariant.Divisible (choose, lose) -- >>> import Data.Void (Void, absurd)--- >>> let po = choose id (totalOrder :: PartialOrder Int) (totalOrder :: PartialOrder String)+-- >>> let po = choose id (totalOrder :: PartialOrder' Int) (totalOrder :: PartialOrder' String) -- >>> runPartialOrder po (Left 1) (Left 2) -- Just LT -- >>> runPartialOrder po (Right "a") (Right "b")@@ -256,42 +290,43 @@ -- -- >>> import Data.Functor.Contravariant.Divisible (lose) -- >>> import Data.Void (Void, absurd)--- >>> let po = lose absurd :: PartialOrder Void+-- >>> let po = lose absurd :: PartialOrder' Void -- >>> seq po () -- ()-instance Decidable PartialOrder where-  lose f = PartialOrder (\a _ -> absurd (f a))-  choose f pb pc = PartialOrder $ \a1 a2 ->-    case (f a1, f a2) of-      (Left b1, Left b2) -> runPartialOrder pb b1 b2-      (Right c1, Right c2) -> runPartialOrder pc c1 c2-      _ -> Nothing+instance (Pro.Representable p, Apply (Pro.Rep p), Monad (Pro.Rep p)) => Decidable (PartialOrder p) where+  lose f = PartialOrder (Pro.tabulate (absurd . f))+  choose f pb pc = PartialOrder $ Pro.tabulate $ \a1 ->+    pure $ Pro.tabulate $ \a2 ->+      case (f a1, f a2) of+        (Left b1, Left b2) -> sieve (runPartialOrder pb) b1 >>= \inner -> sieve inner b2+        (Right c1, Right c2) -> sieve (runPartialOrder pc) c1 >>= \inner -> sieve inner c2+        _ -> pure Nothing  -- | -- >>> import Data.Functor.Contravariant.Divise (divise)--- >>> let po = divise id (totalOrder :: PartialOrder Int) (totalOrder :: PartialOrder Int)+-- >>> let po = divise id (totalOrder :: PartialOrder' Int) (totalOrder :: PartialOrder' Int) -- >>> runPartialOrder po (1, 2) (1, 3) -- Just LT -- >>> runPartialOrder po (1, 2) (1, 2) -- Just EQ-instance Divise PartialOrder where-  divise = divide+instance (Pro.Representable p, Apply (Pro.Rep p)) => Divise (PartialOrder p) where+  divise f pb pc = contramap (fst . f) pb <> contramap (snd . f) pc  -- | -- >>> import Data.Functor.Contravariant.Decide (decide)--- >>> let po = decide id (totalOrder :: PartialOrder Int) (totalOrder :: PartialOrder String)+-- >>> let po = decide id (totalOrder :: PartialOrder' Int) (totalOrder :: PartialOrder' String) -- >>> runPartialOrder po (Left 1) (Left 2) -- Just LT -- >>> runPartialOrder po (Left 1) (Right "a") -- Nothing-instance Decide PartialOrder where+instance (Pro.Representable p, Apply (Pro.Rep p), Monad (Pro.Rep p)) => Decide (PartialOrder p) where   decide = choose  -- | -- >>> import Data.Functor.Contravariant.Conclude (conclude) -- >>> import Data.Void (absurd)--- >>> let po = conclude absurd :: PartialOrder Void+-- >>> let po = conclude absurd :: PartialOrder' Void -- >>> seq po () -- ()-instance Conclude PartialOrder where+instance (Pro.Representable p, Apply (Pro.Rep p), Monad (Pro.Rep p)) => Conclude (PartialOrder p) where   conclude = lose
+ src/Data/Valuation/Poset.hs view
@@ -0,0 +1,354 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -Wall -Werror #-}++-- | A poset (partial order) on a type, generalised over a 'Profunctor' @p@,+-- wrapping @p a (p a 'Bool')@.+-- When @p ~ (->)@, this specialises to @a -> a -> 'Bool'@+-- (see 'Poset'').+--+-- This is a simplified alternative to+-- 'Data.Valuation.PartialOrder.PartialOrder' which wraps+-- @p a (p a ('Maybe' 'Ordering'))@.+-- While 'Data.Valuation.PartialOrder.PartialOrder' distinguishes+-- @LT@, @EQ@, @GT@, and incomparable,+-- 'Poset' only captures the @<=@ relation as a 'Bool'.+--+-- @+-- 'True'   — a <= b+-- 'False'  — a is not <= b (either a > b, or a and b are incomparable)+-- @+module Data.Valuation.Poset+  ( Poset (..),+    Poset',++    -- * optics+    HasPoset (..),+    AsPoset (..),++    -- * combinators+    semigroupPoset,+    runPoset,+    totalPoset,+    comparisonPoset,+    equivalencePoset,+    fromPartialOrder,+    toPartialOrder,+  )+where++import Control.Lens+  ( Lens',+    Prism',+    Rewrapped,+    Wrapped (..),+    iso,+    review,+  )+import Data.Functor.Apply (Apply, liftF2)+import Data.Functor.Contravariant+  ( Comparison (Comparison),+    Contravariant (contramap),+    Equivalence (Equivalence),+  )+import Data.Functor.Contravariant.Conclude (Conclude (..))+import Data.Functor.Contravariant.Decide (Decide (..))+import Data.Functor.Contravariant.Divise (Divise (..))+import Data.Functor.Contravariant.Divisible (Decidable (..), Divisible (..))+import Data.Profunctor (Profunctor (..))+import qualified Data.Profunctor.Rep as Pro+import Data.Profunctor.Sieve (Sieve (..))+import Data.Valuation.PartialOrder+  ( PartialOrder',+    fromLeq,+    partialOrderLeq,+  )+import Data.Valuation.Semigroup+  ( Semigroup',+    applySemigroup,+    runSemigroup,+  )+import Data.Void (absurd)+import Prelude hiding (Semigroup)+import qualified Prelude++-- $setup+-- >>> :set -Wno-name-shadowing -Wno-type-defaults+-- >>> import Data.Void (Void)++-- |+-- >>> runPoset (totalPoset :: Poset' Int) 1 2+-- True+-- >>> runPoset (totalPoset :: Poset' Int) 2 2+-- True+-- >>> runPoset (totalPoset :: Poset' Int) 3 2+-- False+--+-- >>> import qualified Data.Set as Set+-- >>> runPoset (Poset Set.isSubsetOf) (Set.fromList [1,2]) (Set.fromList [2,3 :: Int])+-- False+newtype Poset p a+  = Poset (p a (p a Bool))++type Poset' a =+  Poset (->) a++instance (Poset' a ~ t) => Rewrapped (Poset' a') t++instance Wrapped (Poset' a) where+  type Unwrapped (Poset' a) = a -> a -> Bool+  _Wrapped' = iso (\(Poset x) -> x) Poset++-- | Classy lens for types that contain a 'Poset'.+class HasPoset c p a | c -> p a where+  poset :: Lens' c (Poset p a)++instance HasPoset (Poset p a) p a where+  poset = id++-- | Classy prism for types that can be constructed from a 'Poset'.+class AsPoset c p a | c -> p a where+  _Poset :: Prism' c (Poset p a)++instance AsPoset (Poset p a) p a where+  _Poset = id++-- | Unwrap the poset to its underlying profunctor value.+-- For @p ~ (->)@, this gives @a -> a -> 'Bool'@.+--+-- >>> runPoset (totalPoset :: Poset' Int) 1 2+-- True+-- >>> runPoset (totalPoset :: Poset' Int) 2 2+-- True+-- >>> runPoset (totalPoset :: Poset' Int) 3 2+-- False+runPoset :: Poset p a -> p a (p a Bool)+runPoset (Poset f) = f++-- | Construct a 'Poset' from a total order ('Ord' instance).+-- The result is the standard @<=@ comparison.+--+-- >>> runPoset (totalPoset :: Poset' Int) 1 2+-- True+-- >>> runPoset (totalPoset :: Poset' Int) 2 2+-- True+-- >>> runPoset (totalPoset :: Poset' Int) 3 2+-- False+totalPoset :: (Ord a) => Poset' a+totalPoset = Poset (<=)++-- | Lift a 'Comparison' (a reified total order) into a 'Poset''.+-- The result tests @<=@ according to the comparison.+--+-- >>> import Data.Functor.Contravariant (Comparison(..))+-- >>> runPoset (comparisonPoset (Comparison compare)) (1 :: Int) 2+-- True+-- >>> runPoset (comparisonPoset (Comparison compare)) (2 :: Int) 2+-- True+-- >>> runPoset (comparisonPoset (Comparison compare)) (3 :: Int) 2+-- False+--+-- >>> import Data.Functor.Contravariant (Comparison(..), contramap)+-- >>> runPoset (comparisonPoset (contramap negate (Comparison compare))) (1 :: Int) 2+-- False+comparisonPoset :: Comparison a -> Poset' a+comparisonPoset (Comparison cmp) = Poset (\a1 a2 -> cmp a1 a2 /= GT)++-- | Lift an 'Equivalence' (a reified equivalence relation) into a 'Poset''.+-- The result is the discrete order: @a <= b@ iff @a@ is equivalent to @b@.+--+-- >>> import Data.Functor.Contravariant (Equivalence(..), getEquivalence)+-- >>> let eq = Equivalence (\a b -> a `mod` 3 == b `mod` 3) :: Equivalence Int+-- >>> runPoset (equivalencePoset eq) 1 4+-- True+-- >>> runPoset (equivalencePoset eq) 1 2+-- False+equivalencePoset :: Equivalence a -> Poset' a+equivalencePoset (Equivalence p) = Poset p++-- | Convert a 'PartialOrder'' to a 'Poset'' by extracting the @<=@ relation.+-- Returns 'True' when the partial order yields 'Just' 'LT' or 'Just' 'EQ',+-- 'False' otherwise (including incomparable elements).+--+-- >>> import Data.Valuation.PartialOrder (totalOrder, runPartialOrder)+-- >>> let po = totalOrder :: PartialOrder' Int+-- >>> runPoset (fromPartialOrder po) 1 2+-- True+-- >>> runPoset (fromPartialOrder po) 2 2+-- True+-- >>> runPoset (fromPartialOrder po) 3 2+-- False+--+-- >>> import qualified Data.Set as Set+-- >>> import Data.Valuation.PartialOrder (fromLeq)+-- >>> runPoset (fromPartialOrder (fromLeq Set.isSubsetOf)) (Set.fromList [1,2]) (Set.fromList [2,3 :: Int])+-- False+fromPartialOrder :: PartialOrder' a -> Poset' a+fromPartialOrder po = Poset (partialOrderLeq po)++-- | Convert a 'Poset'' to a 'PartialOrder'' by inferring the full ordering+-- from the @<=@ relation.+--+-- * @a <= b@ and @b <= a@ implies @a = b@ ('Just' 'EQ')+-- * @a <= b@ and not @b <= a@ implies @a < b@ ('Just' 'LT')+-- * not @a <= b@ and @b <= a@ implies @a > b@ ('Just' 'GT')+-- * neither implies incomparable ('Nothing')+--+-- >>> import Data.Valuation.PartialOrder (runPartialOrder)+-- >>> let p = totalPoset :: Poset' Int+-- >>> runPartialOrder (toPartialOrder p) 1 2+-- Just LT+-- >>> runPartialOrder (toPartialOrder p) 2 2+-- Just EQ+-- >>> runPartialOrder (toPartialOrder p) 3 2+-- Just GT+--+-- >>> import qualified Data.Set as Set+-- >>> import Data.Valuation.PartialOrder (runPartialOrder)+-- >>> runPartialOrder (toPartialOrder (Poset Set.isSubsetOf)) (Set.fromList [1,2]) (Set.fromList [2,3 :: Int])+-- Nothing+toPartialOrder :: Poset' a -> PartialOrder' a+toPartialOrder (Poset f) = fromLeq f++-- |+-- >>> import Data.Functor.Contravariant (contramap)+-- >>> runPoset (contramap negate (totalPoset :: Poset' Int)) 1 2+-- False+-- >>> runPoset (contramap negate (totalPoset :: Poset' Int)) 2 1+-- True+instance (Profunctor p) => Contravariant (Poset p) where+  contramap f (Poset g) = Poset (dimap f (lmap f) g)++-- | Conjunction as a first-class 'Semigroup': @a <= b@ in the combined+-- poset iff @a <= b@ in /both/ component posets (the product order).+--+-- >>> let p = totalPoset :: Poset' Int+-- >>> runPoset (runSemigroup semigroupPoset p p) 1 2+-- True+-- >>> runPoset (runSemigroup semigroupPoset p p) 2 2+-- True+-- >>> runPoset (runSemigroup semigroupPoset p p) 3 2+-- False+--+-- Two independent orderings:+--+-- >>> let byVal = totalPoset :: Poset' (Int, Int)+-- >>> let byFst = Poset (\(a,_) (b,_) -> a <= b) :: Poset' (Int, Int)+-- >>> runPoset (runSemigroup semigroupPoset byVal byFst) (1, 2) (1, 3)+-- True+-- >>> runPoset (runSemigroup semigroupPoset byVal byFst) (1, 3) (1, 2)+-- False+semigroupPoset :: (Pro.Representable p, Apply (Pro.Rep p)) => Semigroup' (Poset p a)+semigroupPoset = review applySemigroup $ \(Poset pf) (Poset pg) ->+  Poset $ Pro.tabulate $ \a ->+    liftF2+      ( \innerF innerG -> Pro.tabulate $ \b ->+          liftF2 (&&) (sieve innerF b) (sieve innerG b)+      )+      (sieve pf a)+      (sieve pg a)+{-# SPECIALIZE semigroupPoset :: Semigroup' (Poset' a) #-}++-- |+-- >>> let p = totalPoset :: Poset' Int+-- >>> runPoset (p <> p) 1 2+-- True+-- >>> runPoset (p <> p) 2 2+-- True+-- >>> runPoset (p <> p) 3 2+-- False+instance (Pro.Representable p, Apply (Pro.Rep p)) => Prelude.Semigroup (Poset p a) where+  (<>) = runSemigroup semigroupPoset++-- | The trivial poset where all elements are related: @a <= b@ for all @a@, @b@.+--+-- >>> runPoset (mempty :: Poset' Int) 1 2+-- True+-- >>> runPoset (mempty :: Poset' Int) 42 0+-- True+instance (Pro.Representable p, Apply (Pro.Rep p), Applicative (Pro.Rep p)) => Monoid (Poset p a) where+  mempty = Poset (Pro.tabulate (\_ -> pure (Pro.tabulate (\_ -> pure True))))++-- | Product order: split @a@ into @(b, c)@, check @b <= b'@ and @c <= c'@+-- in both component posets. @conquer@ treats all elements as related.+--+-- >>> import Data.Functor.Contravariant.Divisible (divide, conquer)+-- >>> let p = divide id (totalPoset :: Poset' Int) (totalPoset :: Poset' Int)+-- >>> runPoset p (1, 2) (1, 3)+-- True+-- >>> runPoset p (1, 2) (2, 1)+-- False+-- >>> runPoset p (1, 2) (1, 2)+-- True+--+-- >>> import Data.Functor.Contravariant.Divisible (conquer)+-- >>> runPoset (conquer :: Poset' Int) 1 2+-- True+instance (Pro.Representable p, Apply (Pro.Rep p), Applicative (Pro.Rep p)) => Divisible (Poset p) where+  conquer = mempty+  divide f pb pc = contramap (fst . f) pb <> contramap (snd . f) pc++-- | Disjoint sum: classify @a@ as 'Left' @b@ or 'Right' @c@.+-- Elements on the same side are compared by that side's poset.+-- Elements on different sides are not related ('False').+--+-- >>> import Data.Functor.Contravariant.Divisible (choose, lose)+-- >>> import Data.Void (Void, absurd)+-- >>> let p = choose id (totalPoset :: Poset' Int) (totalPoset :: Poset' String)+-- >>> runPoset p (Left 1) (Left 2)+-- True+-- >>> runPoset p (Right "a") (Right "b")+-- True+-- >>> runPoset p (Left 1) (Right "a")+-- False+-- >>> runPoset p (Right "a") (Left 1)+-- False+--+-- >>> import Data.Functor.Contravariant.Divisible (lose)+-- >>> import Data.Void (Void, absurd)+-- >>> let p = lose absurd :: Poset' Void+-- >>> seq p ()+-- ()+instance (Pro.Representable p, Apply (Pro.Rep p), Monad (Pro.Rep p)) => Decidable (Poset p) where+  lose f = Poset (Pro.tabulate (absurd . f))+  choose f pb pc = Poset $ Pro.tabulate $ \a1 ->+    pure $ Pro.tabulate $ \a2 ->+      case (f a1, f a2) of+        (Left b1, Left b2) -> sieve (runPoset pb) b1 >>= \inner -> sieve inner b2+        (Right c1, Right c2) -> sieve (runPoset pc) c1 >>= \inner -> sieve inner c2+        _ -> pure False++-- |+-- >>> import Data.Functor.Contravariant.Divise (divise)+-- >>> let p = divise id (totalPoset :: Poset' Int) (totalPoset :: Poset' Int)+-- >>> runPoset p (1, 2) (1, 3)+-- True+-- >>> runPoset p (1, 2) (1, 2)+-- True+-- >>> runPoset p (1, 2) (2, 1)+-- False+instance (Pro.Representable p, Apply (Pro.Rep p)) => Divise (Poset p) where+  divise f pb pc = contramap (fst . f) pb <> contramap (snd . f) pc++-- |+-- >>> import Data.Functor.Contravariant.Decide (decide)+-- >>> let p = decide id (totalPoset :: Poset' Int) (totalPoset :: Poset' String)+-- >>> runPoset p (Left 1) (Left 2)+-- True+-- >>> runPoset p (Left 1) (Right "a")+-- False+instance (Pro.Representable p, Apply (Pro.Rep p), Monad (Pro.Rep p)) => Decide (Poset p) where+  decide = choose++-- |+-- >>> import Data.Functor.Contravariant.Conclude (conclude)+-- >>> import Data.Void (absurd)+-- >>> let p = conclude absurd :: Poset' Void+-- >>> seq p ()+-- ()+instance (Pro.Representable p, Apply (Pro.Rep p), Monad (Pro.Rep p)) => Conclude (Poset p) where+  conclude = lose
+ src/Data/Valuation/Presheaf.hs view
@@ -0,0 +1,271 @@+{-# LANGUAGE RankNTypes #-}+{-# OPTIONS_GHC -Wall -Werror #-}++-- | A reified presheaf: a contravariant mapping from one category to another,+-- wrapping @forall a b. cat a b -> cat' (f b) (f a)@.+--+-- 'Presheaf' @cat cat' f@ reifies the action of a contravariant functor on+-- a type constructor @f@, generalised over a source category @cat@ and a+-- target category @cat'@. When both are @(->)@, this specialises to+-- 'Presheaf'' @f@ wrapping @forall a b. (a -> b) -> f b -> f a@, which is+-- exactly 'Data.Functor.Contravariant.contramap'.+--+-- Unlike 'Data.Functor.Contravariant.Contravariant' which is a type class+-- (one instance per type), this is a value — and it is generalised over the+-- source and target categories.+--+-- @+-- newtype 'Presheaf' cat cat' f = 'Presheaf' (forall a b. cat a b -> cat' (f b) (f a))+-- type 'Presheaf'' f = 'Presheaf' (->) (->) f+-- @+module Data.Valuation.Presheaf+  ( Presheaf (..),+    Presheaf',++    -- * combinators+    runPresheaf,+    composePresheafFunctor,+    composeFunctorPresheaf,+    composePresheaf,+    contramapPresheaf,++    -- * presheaf values+    predicatePresheaf,+    comparisonPresheaf,+    equivalencePresheaf,+    proxyPresheaf,+    constPresheaf,++    -- * laws+    lawPresheafIdentity,+    lawPresheafComposition,+  )+where++import Data.Functor.Compose (Compose (..))+import Data.Functor.Const (Const (..))+import Data.Functor.Contravariant+  ( Comparison (..),+    Contravariant (contramap),+    Equivalence (..),+    Predicate (..),+  )+import Data.Profunctor (Profunctor (dimap))+import Data.Proxy (Proxy)+import Data.Valuation.CovariantFunctor (CovariantFunctor (..))++-- $setup+-- >>> :set -Wno-name-shadowing -Wno-type-defaults+-- >>> import Data.Functor.Contravariant (Predicate(..), getPredicate, Comparison(..), getComparison, Equivalence(..), getEquivalence)+-- >>> import Data.Functor.Const (Const(..))+-- >>> import Data.Proxy (Proxy(..))++-- |+-- >>> getPredicate (runPresheaf predicatePresheaf (+1) (Predicate even)) 3+-- True+-- >>> getPredicate (runPresheaf predicatePresheaf (+1) (Predicate even)) 4+-- False+--+-- >>> getComparison (runPresheaf comparisonPresheaf negate (Comparison compare :: Comparison Int)) 1 2+-- GT+newtype Presheaf cat cat' f = Presheaf (forall a b. cat a b -> cat' (f b) (f a))++-- | A 'Presheaf' specialised to @(->)@ for both categories.+-- Wraps @forall a b. (a -> b) -> f b -> f a@, equivalent to+-- 'Data.Functor.Contravariant.contramap'.+type Presheaf' f = Presheaf (->) (->) f++-- | Unwrap a 'Presheaf' to its underlying natural transformation.+--+-- >>> getPredicate (runPresheaf predicatePresheaf (+1) (Predicate even)) 3+-- True+-- >>> getPredicate (runPresheaf predicatePresheaf (+1) (Predicate even)) 4+-- False+--+-- >>> getComparison (runPresheaf comparisonPresheaf negate (Comparison compare :: Comparison Int)) 1 2+-- GT+-- >>> getComparison (runPresheaf comparisonPresheaf negate (Comparison compare :: Comparison Int)) 2 1+-- LT+runPresheaf :: Presheaf cat cat' f -> cat a b -> cat' (f b) (f a)+runPresheaf (Presheaf f) = f++-- | Compose a 'Presheaf' (contravariant) with a 'CovariantFunctor' (covariant).+-- The result is contravariant (contravariant ∘ covariant = contravariant).+--+-- Given @f@ contravariant from @cat@ to @cat'@ and @g@ covariant from @cat'@ to @cat''@,+-- @g ∘ f@ is contravariant from @cat@ to @cat''@ acting on @'Compose' g f@.+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> import Data.Valuation.CovariantFunctor (CovariantFunctor(..), proxyCovariantFunctor, maybeCovariantFunctor)+-- >>> let p = composePresheafFunctor constPresheaf proxyCovariantFunctor+-- >>> runPresheaf p not (Compose (Proxy :: Proxy (Const Int Bool)))+-- Compose Proxy+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> import Data.Valuation.CovariantFunctor (CovariantFunctor(..), maybeCovariantFunctor)+-- >>> let p = composePresheafFunctor constPresheaf maybeCovariantFunctor+-- >>> runPresheaf p not (Compose (Just (Const 42 :: Const Int Bool)))+-- Compose (Just (Const 42))+-- >>> runPresheaf p not (Compose Nothing :: Compose Maybe (Const Int) Bool)+-- Compose Nothing+composePresheafFunctor ::+  (Profunctor cat'') =>+  Presheaf cat cat' f ->+  CovariantFunctor cat' cat'' g ->+  Presheaf cat cat'' (Compose g f)+composePresheafFunctor (Presheaf f) (CovariantFunctor g) =+  Presheaf (dimap getCompose Compose . g . f)++-- | Compose a 'CovariantFunctor' (covariant) with a 'Presheaf' (contravariant).+-- The result is contravariant (covariant ∘ contravariant = contravariant).+--+-- Given @f@ covariant from @cat@ to @cat'@ and @g@ contravariant from @cat'@ to @cat''@,+-- @g ∘ f@ is contravariant from @cat@ to @cat''@ acting on @'Compose' g f@.+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> import Data.Valuation.CovariantFunctor (CovariantFunctor(..), proxyCovariantFunctor, maybeCovariantFunctor)+-- >>> let p = composeFunctorPresheaf proxyCovariantFunctor constPresheaf+-- >>> runPresheaf p not (Compose (Const 42 :: Const Int (Proxy Bool)))+-- Compose (Const 42)+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> import Data.Valuation.CovariantFunctor (CovariantFunctor(..), maybeCovariantFunctor)+-- >>> let p = composeFunctorPresheaf maybeCovariantFunctor constPresheaf+-- >>> runPresheaf p not (Compose (Const 42 :: Const Int (Maybe Bool)))+-- Compose (Const 42)+composeFunctorPresheaf ::+  (Profunctor cat'') =>+  CovariantFunctor cat cat' f ->+  Presheaf cat' cat'' g ->+  Presheaf cat cat'' (Compose g f)+composeFunctorPresheaf (CovariantFunctor f) (Presheaf g) =+  Presheaf (dimap getCompose Compose . g . f)++-- | Compose two presheaves (contravariant functors) to obtain a covariant functor.+-- The result is covariant (contravariant ∘ contravariant = covariant).+--+-- Given @f@ contravariant from @cat@ to @cat'@ and @g@ contravariant from @cat'@ to @cat''@,+-- @g ∘ f@ is covariant from @cat@ to @cat''@ acting on @'Compose' g f@.+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> import Data.Valuation.CovariantFunctor (CovariantFunctor(..), runCovariantFunctor)+-- >>> let p = composePresheaf constPresheaf proxyPresheaf+-- >>> runCovariantFunctor p not (Compose (Proxy :: Proxy (Const Int Bool)))+-- Compose Proxy+--+-- >>> import Data.Functor.Compose (Compose(..))+-- >>> import Data.Valuation.CovariantFunctor (CovariantFunctor(..), runCovariantFunctor)+-- >>> let p = composePresheaf proxyPresheaf constPresheaf+-- >>> runCovariantFunctor p not (Compose (Const Proxy :: Const (Proxy Bool) (Proxy Bool)))+-- Compose (Const Proxy)+composePresheaf ::+  (Profunctor cat'') =>+  Presheaf cat cat' f ->+  Presheaf cat' cat'' g ->+  CovariantFunctor cat cat'' (Compose g f)+composePresheaf (Presheaf f) (Presheaf g) =+  CovariantFunctor (dimap getCompose Compose . g . f)++-- | The canonical 'Presheaf'' for any 'Data.Functor.Contravariant.Contravariant' functor,+-- using 'Data.Functor.Contravariant.contramap'.+--+-- >>> getPredicate (runPresheaf contramapPresheaf abs (Predicate (> 3) :: Predicate Int)) (-5)+-- True+-- >>> getPredicate (runPresheaf contramapPresheaf abs (Predicate (> 3) :: Predicate Int)) (-2)+-- False+--+-- >>> getEquivalence (runPresheaf contramapPresheaf (`mod` 3) (Equivalence (==) :: Equivalence Int)) 4 7+-- True+-- >>> getEquivalence (runPresheaf contramapPresheaf (`mod` 3) (Equivalence (==) :: Equivalence Int)) 4 6+-- False+contramapPresheaf :: (Contravariant f) => Presheaf' f+contramapPresheaf = Presheaf contramap++-- | 'Presheaf'' on 'Predicate': pulls back a predicate along a function.+--+-- >>> getPredicate (runPresheaf predicatePresheaf even (Predicate not)) 2+-- False+-- >>> getPredicate (runPresheaf predicatePresheaf even (Predicate not)) 3+-- True+--+-- >>> getPredicate (runPresheaf predicatePresheaf abs (Predicate (> 3) :: Predicate Int)) (-5)+-- True+-- >>> getPredicate (runPresheaf predicatePresheaf abs (Predicate (> 3) :: Predicate Int)) (-2)+-- False+predicatePresheaf :: Presheaf' Predicate+predicatePresheaf = Presheaf contramap++-- | 'Presheaf'' on 'Comparison': pulls back a comparison along a function.+--+-- >>> getComparison (runPresheaf comparisonPresheaf negate (Comparison compare :: Comparison Int)) 1 2+-- GT+-- >>> getComparison (runPresheaf comparisonPresheaf negate (Comparison compare :: Comparison Int)) 2 1+-- LT+--+-- >>> getComparison (runPresheaf comparisonPresheaf length (Comparison compare :: Comparison Int)) "hi" "hello"+-- LT+comparisonPresheaf :: Presheaf' Comparison+comparisonPresheaf = Presheaf contramap++-- | 'Presheaf'' on 'Equivalence': pulls back an equivalence relation along a function.+--+-- >>> getEquivalence (runPresheaf equivalencePresheaf even (Equivalence (==) :: Equivalence Bool)) 2 4+-- True+-- >>> getEquivalence (runPresheaf equivalencePresheaf even (Equivalence (==) :: Equivalence Bool)) 2 3+-- False+--+-- >>> getEquivalence (runPresheaf equivalencePresheaf (`mod` 3) (Equivalence (==) :: Equivalence Int)) 4 7+-- True+equivalencePresheaf :: Presheaf' Equivalence+equivalencePresheaf = Presheaf contramap++-- | 'Presheaf'' on 'Proxy': trivially maps the phantom type parameter.+--+-- >>> runPresheaf proxyPresheaf not (Proxy :: Proxy Bool)+-- Proxy+--+-- >>> runPresheaf proxyPresheaf length (Proxy :: Proxy Int)+-- Proxy+proxyPresheaf :: Presheaf' Proxy+proxyPresheaf = Presheaf contramap++-- | 'Presheaf'' on @'Const' r@: trivially maps the phantom second parameter.+-- The constant value is preserved.+--+-- >>> runPresheaf constPresheaf not (Const 42 :: Const Int Bool)+-- Const 42+--+-- >>> runPresheaf constPresheaf length (Const "hello" :: Const String Int)+-- Const "hello"+constPresheaf :: Presheaf' (Const r)+constPresheaf = Presheaf contramap++-- | The identity law for a 'Presheaf'': mapping the identity morphism+-- must be the identity on @f a@.+--+-- @+-- 'runPresheaf' p 'id' x == x+-- @+--+-- >>> lawPresheafIdentity proxyPresheaf (Proxy :: Proxy Int)+-- True+-- >>> lawPresheafIdentity constPresheaf (Const 42 :: Const Int Bool)+-- True+lawPresheafIdentity :: (Eq (f a)) => Presheaf' f -> f a -> Bool+lawPresheafIdentity p x =+  runPresheaf p id x == x++-- | The composition law for a 'Presheaf'': mapping a composition must+-- equal composing the individual mappings, with contravariant reversal.+--+-- @+-- 'runPresheaf' p (g '.' f) x == 'runPresheaf' p f ('runPresheaf' p g x)+-- @+--+-- >>> lawPresheafComposition proxyPresheaf not (&&True) (Proxy :: Proxy Bool)+-- True+-- >>> lawPresheafComposition constPresheaf (+1) (*2) (Const "hello" :: Const String Int)+-- True+lawPresheafComposition :: (Eq (f a)) => Presheaf' f -> (b -> c) -> (a -> b) -> f c -> Bool+lawPresheafComposition p g f x =+  runPresheaf p (g . f) x == runPresheaf p f (runPresheaf p g x)
src/Data/Valuation/PresheafValuationAlgebra.hs view
@@ -19,6 +19,7 @@   ( PresheafValuationAlgebra (..),     PresheafValuationAlgebra',     SetPresheafValuationAlgebra,+    SetPresheafValuationAlgebra',     HasPresheafValuationAlgebra (..),     AsPresheafValuationAlgebra (..),     marginalise,@@ -79,53 +80,56 @@ -- | -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> let v1 = Valuation (Set.fromList [1,2]) 10 :: Valuation Set Int Int -- >>> let v2 = Valuation (Set.fromList [2,3]) 20 -- >>> combine pva v1 v2 -- Valuation (fromList [1,2,3]) 30-data PresheafValuationAlgebra p v set var+data PresheafValuationAlgebra p q r s v set var   = PresheafValuationAlgebra       -- | lattice structure on domains       (DomainLattice p (set var) (set var))       -- | the valuation algebra-      (ValuationAlgebra p v set var)+      (ValuationAlgebra q r s v set var)  type PresheafValuationAlgebra' v set var =-  PresheafValuationAlgebra (->) v set var+  PresheafValuationAlgebra (->) (->) (->) (->) v set var  -- | A 'PresheafValuationAlgebra' specialised to 'Set'.-type SetPresheafValuationAlgebra p v var =-  PresheafValuationAlgebra p v Set var+type SetPresheafValuationAlgebra p q r s v var =+  PresheafValuationAlgebra p q r s v Set var +type SetPresheafValuationAlgebra' v var =+  SetPresheafValuationAlgebra (->) (->) (->) (->) v var+ -- | Classy lens for types that contain a 'PresheafValuationAlgebra'.-class HasPresheafValuationAlgebra c p v set var | c -> p v set var where-  presheafValuationAlgebra :: Lens' c (PresheafValuationAlgebra p v set var)+class HasPresheafValuationAlgebra c p q r s v set var | c -> p q r s v set var where+  presheafValuationAlgebra :: Lens' c (PresheafValuationAlgebra p q r s v set var) -instance HasPresheafValuationAlgebra (PresheafValuationAlgebra p v set var) p v set var where+instance HasPresheafValuationAlgebra (PresheafValuationAlgebra p q r s v set var) p q r s v set var where   presheafValuationAlgebra = id  -- | Classy prism for types that can be constructed from a 'PresheafValuationAlgebra'.-class AsPresheafValuationAlgebra c p v set var | c -> p v set var where-  _PresheafValuationAlgebra :: Prism' c (PresheafValuationAlgebra p v set var)+class AsPresheafValuationAlgebra c p q r s v set var | c -> p q r s v set var where+  _PresheafValuationAlgebra :: Prism' c (PresheafValuationAlgebra p q r s v set var) -instance AsPresheafValuationAlgebra (PresheafValuationAlgebra p v set var) p v set var where+instance AsPresheafValuationAlgebra (PresheafValuationAlgebra p q r s v set var) p q r s v set var where   _PresheafValuationAlgebra = id -instance HasDomainLattice (PresheafValuationAlgebra p v set var) p (set var) (set var) where+instance HasDomainLattice (PresheafValuationAlgebra p q r s v set var) p (set var) (set var) where   domainLattice f (PresheafValuationAlgebra l a) = fmap (`PresheafValuationAlgebra` a) (f l) -instance HasValuationAlgebra (PresheafValuationAlgebra p v set var) p v set var where+instance HasValuationAlgebra (PresheafValuationAlgebra p q r s v set var) q r s v set var where   valuationAlgebra f (PresheafValuationAlgebra l a) = fmap (PresheafValuationAlgebra l) (f a) -instance HasSemiValuationAlgebra (PresheafValuationAlgebra p v set var) p v set var where+instance HasSemiValuationAlgebra (PresheafValuationAlgebra p q r s v set var) q r s v set var where   semiValuationAlgebra = valuationAlgebra . semiValuationAlgebra -instance HasSemigroup (PresheafValuationAlgebra p v set var) p v where+instance HasSemigroup (PresheafValuationAlgebra p q r s v set var) q v where   semigroup = semiValuationAlgebra . semigroup -instance HasProjectValuation (PresheafValuationAlgebra p v set var) p v set var where+instance HasProjectValuation (PresheafValuationAlgebra p q r s v set var) r s v set var where   projectValuation = semiValuationAlgebra . projectValuation  -- | Marginalise a valuation to a subdomain: the restriction map of the presheaf.@@ -139,14 +143,14 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + Set.size s))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> marginalise pva (Set.fromList [1]) (Valuation (Set.fromList [1,2]) 10) -- Valuation (fromList [1]) 11 {-# SPECIALIZE marginalise ::-  PresheafValuationAlgebra (->) v set var -> set var -> Valuation set var v -> Valuation set var v+  PresheafValuationAlgebra' v set var -> set var -> Valuation set var v -> Valuation set var v   #-}-marginalise :: (HasProjectValuation algebra (->) v set var, HasValuation valuation set' var' v) => algebra -> set var -> valuation -> Valuation set var v+marginalise :: (HasProjectValuation algebra (->) (->) v set var, HasValuation valuation set' var' v) => algebra -> set var -> valuation -> Valuation set var v marginalise algebra targetDomain =   Valuation targetDomain . view (projectValuation . _Wrapped) algebra targetDomain . view valuationInformation @@ -159,22 +163,22 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> combine pva (Valuation (Set.fromList [1,2]) 10) (Valuation (Set.fromList [2,3]) 20) -- Valuation (fromList [1,2,3]) 30 -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (*)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 1)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 1)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> combine pva (Valuation (Set.fromList [1]) 3) (Valuation (Set.fromList [2]) 4) -- Valuation (fromList [1,2]) 12 {-# SPECIALIZE combine ::-  PresheafValuationAlgebra (->) v set var -> Valuation set var v -> Valuation set var v -> Valuation set var v+  PresheafValuationAlgebra' v set var -> Valuation set var v -> Valuation set var v -> Valuation set var v   #-} combine ::-  (HasSemigroup s1 (->) a, HasDomainLattice s1 (->) (set var) p, HasValuation s2 set var a, HasValuation s3 set var a) => s1 -> s2 -> s3 -> Valuation set var a+  (HasSemigroup s1 (->) a, HasDomainLattice s1 (->) (set var) (set var), HasValuation s2 set var a, HasValuation s3 set var a) => s1 -> s2 -> s3 -> Valuation set var a combine alg phi =   Valuation . runSemigroup (view domainLatticeJoin alg) (view valuationDomain phi) . view valuationDomain <*> runSemigroup (view semigroup alg) (view valuationInformation phi) . view valuationInformation @@ -183,14 +187,14 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 99)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 99)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> neutralValuation pva (Set.fromList [1,2]) -- Valuation (fromList [1,2]) 0 {-# SPECIALIZE neutralValuation ::-  PresheafValuationAlgebra (->) v set var -> set var -> Valuation set var v+  PresheafValuationAlgebra' v set var -> set var -> Valuation set var v   #-}-neutralValuation :: (HasValuationAlgebra s (->) a set var) => s -> set var -> Valuation set var a+neutralValuation :: (HasValuationAlgebra s (->) (->) (->) a set var) => s -> set var -> Valuation set var a neutralValuation algebra =   Valuation <*> view (valuationAlgebra . valuationAlgebraUnit . _Wrapped) algebra @@ -199,14 +203,14 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 99)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 99)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> nullValuation pva (Set.fromList [1,2]) -- Valuation (fromList [1,2]) 99 {-# SPECIALIZE nullValuation ::-  PresheafValuationAlgebra (->) v set var -> set var -> Valuation set var v+  PresheafValuationAlgebra' v set var -> set var -> Valuation set var v   #-}-nullValuation :: (HasValuationAlgebra s (->) a set var) => s -> set var -> Valuation set var a+nullValuation :: (HasValuationAlgebra s (->) (->) (->) a set var) => s -> set var -> Valuation set var a nullValuation algebra =   Valuation <*> view (valuationAlgebra . valuationAlgebraZero . _Wrapped) algebra @@ -215,30 +219,30 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> let sg = presheafCombineSemigroup pva -- >>> runSemigroup sg (Valuation (Set.fromList [1]) 10) (Valuation (Set.fromList [2]) 20) -- Valuation (fromList [1,2]) 30 {-# SPECIALIZE presheafCombineSemigroup ::-  PresheafValuationAlgebra (->) v set var -> Semigroup' (Valuation set var v)+  PresheafValuationAlgebra' v set var -> Semigroup' (Valuation set var v)   #-}-presheafCombineSemigroup :: (HasSemigroup algebra (->) v, HasDomainLattice algebra (->) (set var) p) => algebra -> Semigroup' (Valuation set var v)+presheafCombineSemigroup :: (HasSemigroup algebra (->) v, HasDomainLattice algebra (->) (set var) (set var)) => algebra -> Semigroup' (Valuation set var v) presheafCombineSemigroup = review applySemigroup . combine  -- | Transitivity of marginalisation: @(phi↓d')↓d'' = phi↓d''@ for @d'' <= d' <= d(phi)@. -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> let phi = Valuation (Set.fromList [1,2,3]) 10 -- >>> lawTransitivity pva (Set.fromList [1,2]) (Set.fromList [1]) phi -- True {-# SPECIALIZE lawTransitivity ::-  (Eq v) => PresheafValuationAlgebra (->) v set var -> set var -> set var -> Valuation set var v -> Bool+  (Eq v) => PresheafValuationAlgebra' v set var -> set var -> set var -> Valuation set var v -> Bool   #-}-lawTransitivity :: (Eq a, HasProjectValuation p (->) a set var, HasValuation q set' var' a) => p -> set var -> set var -> q -> Bool+lawTransitivity :: (Eq a, HasProjectValuation p (->) (->) a set var, HasValuation q set' var' a) => p -> set var -> set var -> q -> Bool lawTransitivity pva d' d'' phi =   let step = marginalise pva d'' (marginalise pva d' phi)       direct = marginalise pva d'' phi@@ -249,14 +253,14 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> lawCombinationDomain pva (Valuation (Set.fromList [1,2]) 10) (Valuation (Set.fromList [2,3]) 20) -- True {-# SPECIALIZE lawCombinationDomain ::-  (Eq (set var)) => PresheafValuationAlgebra (->) v set var -> Valuation set var v -> Valuation set var v -> Bool+  (Eq (set var)) => PresheafValuationAlgebra' v set var -> Valuation set var v -> Valuation set var v -> Bool   #-}-lawCombinationDomain :: (HasSemigroup s1 (->) a, Eq (set var), HasValuation s2 set var a, HasValuation s3 set var a, HasDomainLattice s1 (->) (set var) p) => s1 -> s2 -> s3 -> Bool+lawCombinationDomain :: (HasSemigroup s1 (->) a, Eq (set var), HasValuation s2 set var a, HasValuation s3 set var a, HasDomainLattice s1 (->) (set var) (set var)) => s1 -> s2 -> s3 -> Bool lawCombinationDomain pva val1 val2 =   let lat = view domainLattice pva       d1 = view valuationDomain val1@@ -268,14 +272,14 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> lawMarginalisationIdentity pva (Valuation (Set.fromList [1,2]) 42) -- True {-# SPECIALIZE lawMarginalisationIdentity ::-  (Eq (set var), Eq v) => PresheafValuationAlgebra (->) v set var -> Valuation set var v -> Bool+  (Eq (set var), Eq v) => PresheafValuationAlgebra' v set var -> Valuation set var v -> Bool   #-}-lawMarginalisationIdentity :: (Eq a, Eq (set var), HasValuation s set var a, HasProjectValuation p (->) a set var) => p -> s -> Bool+lawMarginalisationIdentity :: (Eq a, Eq (set var), HasValuation s set var a, HasProjectValuation p (->) (->) a set var) => p -> s -> Bool lawMarginalisationIdentity pva val =   let d = view valuationDomain val       v = view valuationInformation val@@ -287,15 +291,15 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> let phi = Valuation (Set.fromList [1]) 42 -- >>> lawNeutralCombination pva (Set.fromList [1,2]) phi -- True {-# SPECIALIZE lawNeutralCombination ::-  (Eq (set var), Eq v) => PresheafValuationAlgebra (->) v set var -> set var -> Valuation set var v -> Bool+  (Eq (set var), Eq v) => PresheafValuationAlgebra' v set var -> set var -> Valuation set var v -> Bool   #-}-lawNeutralCombination :: (HasSemigroup s1 (->) a, Eq a, Eq (set var), HasDomainLattice s1 (->) (set var) (set var), HasValuation s2 set var a, HasValuationAlgebra s1 (->) a set var) => s1 -> set var -> s2 -> Bool+lawNeutralCombination :: (HasSemigroup s1 (->) a, Eq a, Eq (set var), HasDomainLattice s1 (->) (set var) (set var), HasValuation s2 set var a, HasValuationAlgebra s1 (->) (->) (->) a set var) => s1 -> set var -> s2 -> Bool lawNeutralCombination pva d phi =   let lat = view domainLattice pva       dPhi = view valuationDomain phi@@ -309,15 +313,15 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (*)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 1)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 1)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> let phi = Valuation (Set.fromList [1]) 42 -- >>> lawNullCombination pva (Set.fromList [2]) phi -- True {-# SPECIALIZE lawNullCombination ::-  (Eq (set var), Eq v) => PresheafValuationAlgebra (->) v set var -> set var -> Valuation set var v -> Bool+  (Eq (set var), Eq v) => PresheafValuationAlgebra' v set var -> set var -> Valuation set var v -> Bool   #-}-lawNullCombination :: (HasSemigroup s1 (->) a, Eq a, Eq (set var), HasValuation s2 set var a, HasDomainLattice s1 (->) (set var) p, HasValuationAlgebra s1 (->) a set var) => s1 -> set var -> s2 -> Bool+lawNullCombination :: (HasSemigroup s1 (->) a, Eq a, Eq (set var), HasValuation s2 set var a, HasDomainLattice s1 (->) (set var) (set var), HasValuationAlgebra s1 (->) (->) (->) a set var) => s1 -> set var -> s2 -> Bool lawNullCombination pva d phi =   let lat = view domainLattice pva       dPhi = view valuationDomain phi@@ -332,14 +336,14 @@ -- -- >>> let lat = setDomainLattice :: DomainLattice (->) (Set Int) (Set Int) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\_ v -> v))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int Set Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 0)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int Set Int -- >>> let pva = PresheafValuationAlgebra lat va -- >>> lawCombinationCommutative pva (Valuation (Set.fromList [1]) 10) (Valuation (Set.fromList [2]) 20) -- True {-# SPECIALIZE lawCombinationCommutative ::-  (Eq (set var), Eq v) => PresheafValuationAlgebra (->) v set var -> Valuation set var v -> Valuation set var v -> Bool+  (Eq (set var), Eq v) => PresheafValuationAlgebra' v set var -> Valuation set var v -> Valuation set var v -> Bool   #-}-lawCombinationCommutative :: (HasSemigroup s1 (->) a, Eq a, Eq (set var), HasDomainLattice s1 (->) (set var) p, HasValuation s2 set var a, HasValuation s3 set var a) => s1 -> s2 -> s3 -> Bool+lawCombinationCommutative :: (HasSemigroup s1 (->) a, Eq a, Eq (set var), HasDomainLattice s1 (->) (set var) (set var), HasValuation s2 set var a, HasValuation s3 set var a) => s1 -> s2 -> s3 -> Bool lawCombinationCommutative pva phi psi =   let Valuation d1 v1 = combine pva phi psi       Valuation d2 v2 = combine pva psi phi
src/Data/Valuation/ProjectValuation.hs view
@@ -10,6 +10,7 @@   ( ProjectValuation (..),     ProjectValuation',     SetProjectValuation,+    SetProjectValuation',      -- * optics     HasProjectValuation (..),@@ -59,76 +60,76 @@ -- -- >>> let ProjectValuation f = ProjectValuation (\s v -> v + length s) in f [1,2,3] (10 :: Int) -- 13-newtype ProjectValuation p v set var-  = ProjectValuation (p (set var) (p v v))+newtype ProjectValuation p q v set var+  = ProjectValuation (p (set var) (q v v))  type ProjectValuation' v set var =-  ProjectValuation (->) v set var+  ProjectValuation (->) (->) v set var  instance-  (ProjectValuation p v set var ~ t) =>-  Rewrapped (ProjectValuation p' v' set' var') t+  (ProjectValuation p q v set var ~ t) =>+  Rewrapped (ProjectValuation p' q' v' set' var') t -instance Wrapped (ProjectValuation p v set var) where-  type Unwrapped (ProjectValuation p v set var) = p (set var) (p v v)+instance Wrapped (ProjectValuation p q v set var) where+  type Unwrapped (ProjectValuation p q v set var) = p (set var) (q v v)   _Wrapped' = iso (\(ProjectValuation x) -> x) ProjectValuation  -- | Classy lens for types that contain a 'ProjectValuation'.-class HasProjectValuation c p v set var | c -> p v set var where-  projectValuation :: Lens' c (ProjectValuation p v set var)+class HasProjectValuation c p q v set var | c -> p q v set var where+  projectValuation :: Lens' c (ProjectValuation p q v set var) -instance HasProjectValuation (ProjectValuation p v set var) p v set var where+instance HasProjectValuation (ProjectValuation p q v set var) p q v set var where   projectValuation = id  -- | Classy prism for types that can be constructed from a 'ProjectValuation'.-class AsProjectValuation c p v set var | c -> p v set var where-  _ProjectValuation :: Prism' c (ProjectValuation p v set var)+class AsProjectValuation c p q v set var | c -> p q v set var where+  _ProjectValuation :: Prism' c (ProjectValuation p q v set var) -instance AsProjectValuation (ProjectValuation p v set var) p v set var where+instance AsProjectValuation (ProjectValuation p q v set var) p q v set var where   _ProjectValuation = id  -- | Lens to the underlying function of a 'HasProjectValuation'.-applyHasProjectValuation :: (HasProjectValuation pv p v set var) => Lens' pv (p (set var) (p v v))+applyHasProjectValuation :: (HasProjectValuation pv p q v set var) => Lens' pv (p (set var) (q v v)) applyHasProjectValuation = projectValuation . _Wrapped  -- | Prism to the underlying function of an 'AsProjectValuation'.-applyAsProjectValuation :: (AsProjectValuation pv p v set var) => Prism' pv (p (set var) (p v v))+applyAsProjectValuation :: (AsProjectValuation pv p q v set var) => Prism' pv (p (set var) (q v v)) applyAsProjectValuation = _ProjectValuation . _Wrapped  -- | -- >>> import Data.Functor.Contravariant (contramap)--- >>> let pv = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int+-- >>> let pv = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = contramap (*2) pv in f [1,2,3] 10 -- 22 -- -- >>> import Data.Functor.Contravariant (contramap)--- >>> let pv = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int+-- >>> let pv = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = contramap negate pv in f [1,2,3] 0 -- -6-instance (Functor set, Profunctor p) => Contravariant (ProjectValuation p v set) where+instance (Functor set, Profunctor p) => Contravariant (ProjectValuation p q v set) where   contramap f (ProjectValuation g) = ProjectValuation (lmap (fmap f) g)  -- | -- >>> import Data.Functor.Contravariant.Divisible (conquer, divide)--- >>> let ProjectValuation f = conquer :: ProjectValuation (->) Int [] Int in f [1,2,3] 42+-- >>> let ProjectValuation f = conquer :: ProjectValuation (->) (->) Int [] Int in f [1,2,3] 42 -- 42 -- -- >>> import Data.Functor.Contravariant.Divisible (conquer, divide)--- >>> let ProjectValuation f = conquer :: ProjectValuation (->) String [] Char in f "abc" "hello"+-- >>> let ProjectValuation f = conquer :: ProjectValuation (->) (->) String [] Char in f "abc" "hello" -- "hello" -- -- >>> import Data.Functor.Contravariant.Divisible (conquer, divide)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = divide (\x -> (x, x * 10)) pvB pvC in f [1,2,3] 5 -- 21 -- -- >>> import Data.Functor.Contravariant.Divisible (conquer, divide)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = divide (\x -> (x, x)) pvB pvC in f [1,2,3] 5 -- 21-instance (Functor set, Strong p, Category p) => Divisible (ProjectValuation p v set) where+instance (Functor set, Strong p, Category p, Category q) => Divisible (ProjectValuation p q v set) where   conquer = ProjectValuation (rmap (const id) id)   divide split (ProjectValuation pb) (ProjectValuation pc) =     let pb' = lmap (fmap (fst . split)) pb@@ -138,27 +139,27 @@ -- | -- >>> import Data.Functor.Contravariant.Divisible (choose, lose) -- >>> import Data.Void (Void, absurd)--- >>> let ProjectValuation f = lose absurd :: ProjectValuation (->) Int [] Void in f [] 42+-- >>> let ProjectValuation f = lose absurd :: ProjectValuation (->) (->) Int [] Void in f [] 42 -- 42 -- -- >>> import Data.Functor.Contravariant.Divisible (choose)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = choose (\x -> if even x then Left x else Right x) pvB pvC in f [1,2,3,4] 10 -- 26 -- -- >>> import Data.Functor.Contravariant.Divisible (choose)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = choose Left pvB pvC in f [1,2,3] 10 -- 6 -- -- >>> import Data.Functor.Contravariant.Divisible (choose)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = choose Right pvB pvC in f [1,2,3] 10 -- 30-instance (Filterable set, Strong p, Category p) => Decidable (ProjectValuation p v set) where+instance (Filterable set, Strong p, Category p, Category q) => Decidable (ProjectValuation p q v set) where   lose _ = ProjectValuation (rmap (const id) id)   choose ch (ProjectValuation pb) (ProjectValuation pc) =     let pb' = lmap (mapMaybe (either Just (const Nothing) . ch)) pb@@ -167,11 +168,11 @@  -- | -- >>> import Data.Functor.Contravariant.Divise (divise)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = divise (\x -> (x, x * 10)) pvB pvC in f [1,2,3] 5 -- 21-instance (Functor set, Strong p, Semigroupoid p) => Divise (ProjectValuation p v set) where+instance (Functor set, Strong p, Semigroupoid p, Semigroupoid q) => Divise (ProjectValuation p q v set) where   divise split (ProjectValuation pb) (ProjectValuation pc) =     let pb' = lmap (fmap (fst . split)) pb         pc' = lmap (fmap (snd . split)) pc@@ -179,11 +180,11 @@  -- | -- >>> import Data.Functor.Contravariant.Decide (decide)--- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pvB = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let pvC = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = decide (\x -> if even x then Left x else Right x) pvB pvC in f [1,2,3,4] 10 -- 26-instance (Filterable set, Strong p, Semigroupoid p) => Decide (ProjectValuation p v set) where+instance (Filterable set, Strong p, Semigroupoid p, Semigroupoid q) => Decide (ProjectValuation p q v set) where   decide ch (ProjectValuation pb) (ProjectValuation pc) =     let pb' = lmap (mapMaybe (either Just (const Nothing) . ch)) pb         pc' = lmap (mapMaybe (either (const Nothing) Just . ch)) pc@@ -192,32 +193,35 @@ -- | -- >>> import Data.Functor.Contravariant.Conclude (conclude) -- >>> import Data.Void (absurd)--- >>> let ProjectValuation f = conclude absurd :: ProjectValuation (->) Int [] Void in f [] 42+-- >>> let ProjectValuation f = conclude absurd :: ProjectValuation (->) (->) Int [] Void in f [] 42 -- 42-instance (Filterable set, Strong p, Semigroupoid p, Category p) => Conclude (ProjectValuation p v set) where+instance (Filterable set, Strong p, Semigroupoid p, Category p, Semigroupoid q, Category q) => Conclude (ProjectValuation p q v set) where   conclude _ = ProjectValuation (rmap (const id) id)  -- | -- >>> let ProjectValuation f = runSemigroup semigroupProjectValuation (ProjectValuation (\_ v -> v + 1)) (ProjectValuation (\_ v -> v * 2)) in f [] (3 :: Int) -- 7-semigroupProjectValuation :: Semigroup' (ProjectValuation (->) v set var)+semigroupProjectValuation :: Semigroup' (ProjectValuation' v set var) semigroupProjectValuation = review applySemigroup (\(ProjectValuation p1) (ProjectValuation p2) -> ProjectValuation (\s -> p1 s . p2 s))  -- |--- >>> let p1 = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int--- >>> let p2 = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let p1 = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int+-- >>> let p2 = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = p1 <> p2 in f [1,2,3] 5 -- 21-instance Prelude.Semigroup (ProjectValuation (->) v set var) where+instance Prelude.Semigroup (ProjectValuation' v set var) where   (<>) = runSemigroup semigroupProjectValuation  -- |--- >>> let p = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int+-- >>> let p = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int -- >>> let ProjectValuation f = mempty <> p in f [1,2,3] 5 -- 11-instance Monoid (ProjectValuation (->) v set var) where+instance Monoid (ProjectValuation' v set var) where   mempty = ProjectValuation (const id)  -- | A 'ProjectValuation' specialised to 'Set'.-type SetProjectValuation p v var =-  ProjectValuation p v Set var+type SetProjectValuation p q v var =+  ProjectValuation p q v Set var++type SetProjectValuation' v var =+  SetProjectValuation (->) (->) v var
src/Data/Valuation/SemiValuationAlgebra.hs view
@@ -7,6 +7,7 @@   ( SemiValuationAlgebra (..),     SemiValuationAlgebra',     SetSemiValuationAlgebra,+    SetSemiValuationAlgebra',      -- * optics     HasSemiValuationAlgebra (..),@@ -54,75 +55,75 @@ -- >>> import Prelude hiding (Semigroup)  -- |--- >>> let SemiValuationAlgebra sg (ProjectValuation p) = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) :: SemiValuationAlgebra (->) Int [] Int+-- >>> let SemiValuationAlgebra sg (ProjectValuation p) = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) :: SemiValuationAlgebra (->) (->) (->) Int [] Int -- >>> runSemigroup sg 3 4 -- 7 -- >>> p [1,2,3] 10 -- 16-data SemiValuationAlgebra p v set var+data SemiValuationAlgebra p q r v set var   = SemiValuationAlgebra       -- | algebra combine       (Semigroup p v)       -- | algebra project-      (ProjectValuation p v set var)+      (ProjectValuation q r v set var)  type SemiValuationAlgebra' v set var =-  SemiValuationAlgebra (->) v set var+  SemiValuationAlgebra (->) (->) (->) v set var  -- | Type-changing lens to the 'ProjectValuation' component.-projectValuation' :: Lens (SemiValuationAlgebra p v set var) (SemiValuationAlgebra p v set' var') (ProjectValuation p v set var) (ProjectValuation p v set' var')+projectValuation' :: Lens (SemiValuationAlgebra p q r v set var) (SemiValuationAlgebra p q' r' v set' var') (ProjectValuation q r v set var) (ProjectValuation q' r' v set' var') projectValuation' f (SemiValuationAlgebra s p) = fmap (SemiValuationAlgebra s) (f p)  -- | Classy lens for types that contain a 'SemiValuationAlgebra'.-class HasSemiValuationAlgebra c p v set var | c -> p v set var where+class HasSemiValuationAlgebra c p q r v set var | c -> p q r v set var where   semiValuationAlgebra ::-    Lens' c (SemiValuationAlgebra p v set var)+    Lens' c (SemiValuationAlgebra p q r v set var) -instance HasSemiValuationAlgebra (SemiValuationAlgebra p v set var) p v set var where+instance HasSemiValuationAlgebra (SemiValuationAlgebra p q r v set var) p q r v set var where   semiValuationAlgebra = id  -- | Classy prism for types that can be constructed from a 'SemiValuationAlgebra'.-class AsSemiValuationAlgebra c p v set var | c -> p v set var where+class AsSemiValuationAlgebra c p q r v set var | c -> p q r v set var where   _SemiValuationAlgebra ::-    Prism' c (SemiValuationAlgebra p v set var)+    Prism' c (SemiValuationAlgebra p q r v set var) -instance AsSemiValuationAlgebra (SemiValuationAlgebra p v set var) p v set var where+instance AsSemiValuationAlgebra (SemiValuationAlgebra p q r v set var) p q r v set var where   _SemiValuationAlgebra = id -instance HasSemigroup (SemiValuationAlgebra p v set var) p v where+instance HasSemigroup (SemiValuationAlgebra p q r v set var) p v where   semigroup f (SemiValuationAlgebra s p) = fmap (`SemiValuationAlgebra` p) (f s) -instance HasProjectValuation (SemiValuationAlgebra p v set var) p v set var where+instance HasProjectValuation (SemiValuationAlgebra p q r v set var) q r v set var where   projectValuation = projectValuation'  -- | -- >>> import Data.Functor.Contravariant (contramap)--- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) :: SemiValuationAlgebra (->) Int [] Int+-- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) :: SemiValuationAlgebra (->) (->) (->) Int [] Int -- >>> let SemiValuationAlgebra sg (ProjectValuation p) = contramap (*2) sva -- >>> runSemigroup sg 3 4 -- 7 -- >>> p [1,2,3] 10 -- 22-instance (Functor set, Profunctor p) => Contravariant (SemiValuationAlgebra p v set) where+instance (Functor set, Profunctor q) => Contravariant (SemiValuationAlgebra p q r v set) where   contramap f (SemiValuationAlgebra s p) = SemiValuationAlgebra s (contramap f p)  -- | -- >>> import Data.Functor.Contravariant.Divisible (conquer, divide)--- >>> let SemiValuationAlgebra sg (ProjectValuation p) = conquer :: SemiValuationAlgebra (->) [Int] [] Int+-- >>> let SemiValuationAlgebra sg (ProjectValuation p) = conquer :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> runSemigroup sg [1,2] [3,4] -- [1,2,3,4] -- >>> p [10,20,30] [42] -- [42] -- -- >>> import Data.Functor.Contravariant.Divisible (conquer, divide)--- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) [Int] [] Int--- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s)) :: SemiValuationAlgebra (->) [Int] [] Int+-- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int+-- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let SemiValuationAlgebra sg (ProjectValuation p) = divide (\x -> (x, x + 10)) sva1 sva2 -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> p [1,2,3] [0] -- [0,13,12,11,1,2,3]-instance (Functor set, Strong p, Arrow p, Prelude.Semigroup v) => Divisible (SemiValuationAlgebra p v set) where+instance (Functor set, Strong q, Profunctor p, Arrow p, Category q, Category r, Prelude.Semigroup v) => Divisible (SemiValuationAlgebra p q r v set) where   conquer = SemiValuationAlgebra (review applySemigroup (rmap arr (arr (<>)))) conquer   divide f (SemiValuationAlgebra s p1) (SemiValuationAlgebra _ p2) =     SemiValuationAlgebra s (divide f p1 p2)@@ -130,62 +131,65 @@ -- | -- >>> import Data.Functor.Contravariant.Divisible (choose, lose) -- >>> import Data.Void (Void, absurd)--- >>> let SemiValuationAlgebra sg (ProjectValuation p) = lose absurd :: SemiValuationAlgebra (->) [Int] [] Void+-- >>> let SemiValuationAlgebra sg (ProjectValuation p) = lose absurd :: SemiValuationAlgebra (->) (->) (->) [Int] [] Void -- >>> runSemigroup sg [1,2] [3,4] -- [1,2,3,4] -- >>> p [] [42] -- [42] -- -- >>> import Data.Functor.Contravariant.Divisible (choose)--- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) [Int] [] Int--- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ map negate s)) :: SemiValuationAlgebra (->) [Int] [] Int+-- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int+-- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ map negate s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let SemiValuationAlgebra sg (ProjectValuation p) = choose (\x -> if even x then Left x else Right x) sva1 sva2 -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> p [1,2,3,4] [0] -- [0,-1,-3,2,4]-instance (Filterable set, Strong p, Arrow p, Prelude.Semigroup v) => Decidable (SemiValuationAlgebra p v set) where+instance (Filterable set, Strong q, Profunctor p, Arrow p, Category q, Category r, Prelude.Semigroup v) => Decidable (SemiValuationAlgebra p q r v set) where   lose f = SemiValuationAlgebra (review applySemigroup (rmap arr (arr (<>)))) (lose f)   choose f (SemiValuationAlgebra s p1) (SemiValuationAlgebra _ p2) =     SemiValuationAlgebra s (choose f p1 p2)  -- | -- >>> import Data.Functor.Contravariant.Divise (divise)--- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) [Int] [] Int--- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s)) :: SemiValuationAlgebra (->) [Int] [] Int+-- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int+-- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let SemiValuationAlgebra sg (ProjectValuation p) = divise (\x -> (x, x + 10)) sva1 sva2 -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> p [1,2,3] [0] -- [0,13,12,11,1,2,3]-instance (Functor set, Strong p, Semigroupoid p) => Divise (SemiValuationAlgebra p v set) where+instance (Functor set, Strong q, Semigroupoid q, Semigroupoid r) => Divise (SemiValuationAlgebra p q r v set) where   divise f (SemiValuationAlgebra s p1) (SemiValuationAlgebra _ p2) =     SemiValuationAlgebra s (divise f p1 p2)  -- | -- >>> import Data.Functor.Contravariant.Decide (decide)--- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) [Int] [] Int--- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ map negate s)) :: SemiValuationAlgebra (->) [Int] [] Int+-- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int+-- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ map negate s)) :: SemiValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let SemiValuationAlgebra sg (ProjectValuation p) = decide (\x -> if even x then Left x else Right x) sva1 sva2 -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> p [1,2,3,4] [0] -- [0,-1,-3,2,4]-instance (Filterable set, Strong p, Semigroupoid p) => Decide (SemiValuationAlgebra p v set) where+instance (Filterable set, Strong q, Semigroupoid q, Semigroupoid r) => Decide (SemiValuationAlgebra p q r v set) where   decide f (SemiValuationAlgebra s p1) (SemiValuationAlgebra _ p2) =     SemiValuationAlgebra s (decide f p1 p2)  -- | -- >>> import Data.Functor.Contravariant.Conclude (conclude) -- >>> import Data.Void (absurd)--- >>> let SemiValuationAlgebra sg (ProjectValuation p) = conclude absurd :: SemiValuationAlgebra (->) [Int] [] Void+-- >>> let SemiValuationAlgebra sg (ProjectValuation p) = conclude absurd :: SemiValuationAlgebra (->) (->) (->) [Int] [] Void -- >>> runSemigroup sg [1,2] [3,4] -- [1,2,3,4] -- >>> p [] [42] -- [42]-instance (Filterable set, Strong p, Semigroupoid p, Arrow p, Prelude.Semigroup v) => Conclude (SemiValuationAlgebra p v set) where+instance (Filterable set, Strong q, Semigroupoid q, Category q, Semigroupoid r, Category r, Profunctor p, Arrow p, Prelude.Semigroup v) => Conclude (SemiValuationAlgebra p q r v set) where   conclude f = SemiValuationAlgebra (review applySemigroup (rmap arr (arr (<>)))) (conclude f)  -- | A 'SemiValuationAlgebra' specialised to 'Set'.-type SetSemiValuationAlgebra p v var =-  SemiValuationAlgebra p v Set var+type SetSemiValuationAlgebra p q r v var =+  SemiValuationAlgebra p q r v Set var++type SetSemiValuationAlgebra' v var =+  SetSemiValuationAlgebra (->) (->) (->) v var
src/Data/Valuation/Semigroup.hs view
@@ -79,6 +79,8 @@     composeG,     productF,     composeF,+    unionSet,+    unionIntSet,      -- * laws     lawAssociative,@@ -112,9 +114,13 @@   ) import Data.Functor.Identity (Identity) import Data.Functor.Product (Product (..))+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet import Data.List.NonEmpty (NonEmpty (..)) import Data.Ord (Down (..)) import Data.Proxy (Proxy (..))+import Data.Set (Set)+import qualified Data.Set as Set import Data.Tuple (Solo) import Data.Void (Void, absurd) import GHC.Conc (STM)@@ -675,3 +681,51 @@ -- Compose [[1,2],[3,4]] composeF :: Semigroup' (f (g a)) -> Semigroup' (Compose f g a) composeF = mapSemigroup getCompose Compose++-- | Semigroup on 'Set' via 'Data.Set.union'.+--+-- >>> import qualified Data.Set as Set+-- >>> runSemigroup unionSet (Set.fromList [1,2]) (Set.fromList [2,3]) :: Set Int+-- fromList [1,2,3]+--+-- >>> import qualified Data.Set as Set+-- >>> runSemigroup unionSet (Set.fromList [1,2,3]) Set.empty :: Set Int+-- fromList [1,2,3]+--+-- >>> import qualified Data.Set as Set+-- >>> runSemigroup unionSet Set.empty (Set.fromList [4,5]) :: Set Int+-- fromList [4,5]+--+-- >>> import qualified Data.Set as Set+-- >>> runSemigroup unionSet (Set.fromList [1,2]) (Set.fromList [1,2]) :: Set Int+-- fromList [1,2]+--+-- >>> import qualified Data.Set as Set+-- >>> lawAssociative unionSet (Set.fromList [1,2]) (Set.fromList [2,3]) (Set.fromList [3,4 :: Int])+-- True+unionSet :: (Ord a) => Semigroup' (Set a)+unionSet = review applySemigroup Set.union++-- | Semigroup on 'IntSet' via 'Data.IntSet.union'.+--+-- >>> import qualified Data.IntSet as IntSet+-- >>> runSemigroup unionIntSet (IntSet.fromList [1,2]) (IntSet.fromList [2,3])+-- fromList [1,2,3]+--+-- >>> import qualified Data.IntSet as IntSet+-- >>> runSemigroup unionIntSet (IntSet.fromList [1,2,3]) IntSet.empty+-- fromList [1,2,3]+--+-- >>> import qualified Data.IntSet as IntSet+-- >>> runSemigroup unionIntSet IntSet.empty (IntSet.fromList [4,5])+-- fromList [4,5]+--+-- >>> import qualified Data.IntSet as IntSet+-- >>> runSemigroup unionIntSet (IntSet.fromList [1,2]) (IntSet.fromList [1,2])+-- fromList [1,2]+--+-- >>> import qualified Data.IntSet as IntSet+-- >>> lawAssociative unionIntSet (IntSet.fromList [1,2]) (IntSet.fromList [2,3]) (IntSet.fromList [3,4])+-- True+unionIntSet :: Semigroup' IntSet+unionIntSet = review applySemigroup IntSet.union
src/Data/Valuation/Valuation.hs view
@@ -20,6 +20,20 @@     combineSemiValuation,     combineValuation,     semigroupValuation,++    -- * laws+    lawFunctorIdentity,+    lawFunctorComposition,+    lawMonadLeftIdentity,+    lawMonadRightIdentity,+    lawMonadAssociativity,+    lawComonadExtractDuplicate,+    lawComonadDuplicateExtract,+    lawComonadAssociativity,+    lawBifunctorIdentity,+    lawBifunctorComposition,+    lawCombineVarAssociative,+    lawCombineVarCommutative,   ) where @@ -48,10 +62,10 @@ import Data.Functor.Extend (Extend (..)) import Data.Semigroup.Traversable.Class (Bitraversable1 (..), Traversable1 (..)) import Data.Set (Set)-import Data.Valuation.ProjectValuation (ProjectValuation (..))-import Data.Valuation.SemiValuationAlgebra (SemiValuationAlgebra (..))+import Data.Valuation.ProjectValuation (ProjectValuation (..), ProjectValuation')+import Data.Valuation.SemiValuationAlgebra (SemiValuationAlgebra (..), SemiValuationAlgebra') import Data.Valuation.Semigroup (Semigroup', applySemigroup, runSemigroup, semigroup')-import Data.Valuation.ValuationAlgebra (ValuationAlgebra (..))+import Data.Valuation.ValuationAlgebra (ValuationAlgebra (..), ValuationAlgebra') import Data.Valuation.ValuationAlgebraOp (ValuationAlgebraOp (..)) import GHC.Generics (Generic, Generic1) import Prelude hiding (Semigroup)@@ -59,6 +73,9 @@  -- $setup -- >>> :set -Wno-name-shadowing -Wno-type-defaults+-- >>> import qualified Data.Set as Set+-- >>> import Control.Lens (review)+-- >>> import Data.Valuation.Semigroup (applySemigroup)  -- | -- >>> Valuation [1,2,3] "hello"@@ -467,15 +484,15 @@     Valuation <$> traverse1 f dom <.> g info  -- |--- >>> let pv = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) Int [] Int+-- >>> let pv = ProjectValuation (\s v -> v + sum s) :: ProjectValuation (->) (->) Int [] Int -- >>> projectVar pv (Valuation [1,2,3] 10) -- 16 ----- >>> let pv = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) Int [] Int+-- >>> let pv = ProjectValuation (\s v -> v * length s) :: ProjectValuation (->) (->) Int [] Int -- >>> projectVar pv (Valuation [1,2,3] 5) -- 15 projectVar ::-  ProjectValuation (->) v set var ->+  ProjectValuation' v set var ->   Valuation set var v ->   v projectVar (ProjectValuation p) (Valuation dom info) =@@ -501,18 +518,18 @@ -- | -- >>> import Control.Lens (review) -- >>> import qualified Data.Valuation.Semigroup as S--- >>> let sva = SemiValuationAlgebra (review S.applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) :: SemiValuationAlgebra (->) Int [] Int+-- >>> let sva = SemiValuationAlgebra (review S.applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) :: SemiValuationAlgebra (->) (->) (->) Int [] Int -- >>> combineSemiValuation S.list sva (Valuation [1,2] 10) (Valuation [3,4] 20) -- Valuation [1,2,3,4] 40 -- -- >>> import Control.Lens (review) -- >>> import qualified Data.Valuation.Semigroup as S--- >>> let sva = SemiValuationAlgebra (review S.applySemigroup (*)) (ProjectValuation (\s v -> v + length s)) :: SemiValuationAlgebra (->) Int [] Int+-- >>> let sva = SemiValuationAlgebra (review S.applySemigroup (*)) (ProjectValuation (\s v -> v + length s)) :: SemiValuationAlgebra (->) (->) (->) Int [] Int -- >>> combineSemiValuation S.list sva (Valuation [1,2] 3) (Valuation [3] 4) -- Valuation [1,2,3] 15 combineSemiValuation ::   Semigroup' (set var) ->-  SemiValuationAlgebra (->) v set var ->+  SemiValuationAlgebra' v set var ->   Valuation set var v ->   Valuation set var v ->   Valuation set var v@@ -525,7 +542,7 @@ -- >>> import qualified Data.Valuation.Semigroup as S -- >>> let sva = SemiValuationAlgebra (review S.applySemigroup (+)) (ProjectValuation (\s v -> v + sum s)) -- >>> import Data.Valuation.ValuationAlgebraOp (ValuationAlgebraOp(..))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp sum) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int [] Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp sum) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int [] Int -- >>> combineValuation S.list va (Valuation [1,2] 10) (Valuation [3,4] 20) -- Valuation [1,2,3,4] 50 --@@ -533,12 +550,12 @@ -- >>> import qualified Data.Valuation.Semigroup as S -- >>> let sva = SemiValuationAlgebra (review S.applySemigroup (*)) (ProjectValuation (\s v -> v + length s)) -- >>> import Data.Valuation.ValuationAlgebraOp (ValuationAlgebraOp(..))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 1)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int [] Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp (const 1)) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int [] Int -- >>> combineValuation S.list va (Valuation [1,2] 3) (Valuation [3] 4) -- Valuation [1,2,3] 15 combineValuation ::   Semigroup' (set var) ->-  ValuationAlgebra (->) v set var ->+  ValuationAlgebra' v set var ->   Valuation set var v ->   Valuation set var v ->   Valuation set var v@@ -579,3 +596,180 @@   Semigroup' (Valuation set var a) semigroupValuation sd sa =   review applySemigroup (\(Valuation d1 a1) (Valuation d2 a2) -> Valuation (runSemigroup sd d1 d2) (runSemigroup sa a1 a2))++-- | Functor identity law: @fmap id v == v@.+--+-- >>> lawFunctorIdentity (Valuation [1,2,3] "hello" :: Valuation [] Int String)+-- True+--+-- >>> lawFunctorIdentity (Valuation [1] (42 :: Int) :: Valuation [] Int Int)+-- True+lawFunctorIdentity :: (Eq (set var), Eq a) => Valuation set var a -> Bool+lawFunctorIdentity v =+  fmap id v == v++-- | Functor composition law: @fmap (f . g) v == fmap f (fmap g v)@.+--+-- >>> lawFunctorComposition length show (Valuation [1,2] (42 :: Int) :: Valuation [] Int Int)+-- True+--+-- >>> lawFunctorComposition (*2) (+1) (Valuation [1,2,3] 10 :: Valuation [] Int Int)+-- True+lawFunctorComposition :: (Eq (set var), Eq c) => (b -> c) -> (a -> b) -> Valuation set var a -> Bool+lawFunctorComposition f g v =+  fmap (f . g) v == fmap f (fmap g v)++-- | Monad left identity law: @return a >>= f == f a@.+--+-- >>> lawMonadLeftIdentity 42 (\x -> Valuation [x] (show x)) :: Bool+-- True+--+-- >>> lawMonadLeftIdentity "hi" (\s -> Valuation [length s] s) :: Bool+-- True+lawMonadLeftIdentity :: (Eq (set var), Eq b, Monoid (set var)) => a -> (a -> Valuation set var b) -> Bool+lawMonadLeftIdentity a f =+  (return a >>= f) == f a++-- | Monad right identity law: @m >>= return == m@.+--+-- >>> lawMonadRightIdentity (Valuation [1,2,3] "hello" :: Valuation [] Int String)+-- True+--+-- >>> lawMonadRightIdentity (Valuation [] (42 :: Int) :: Valuation [] Int Int)+-- True+lawMonadRightIdentity :: (Eq (set var), Eq a, Monoid (set var)) => Valuation set var a -> Bool+lawMonadRightIdentity m =+  (m >>= return) == m++-- | Monad associativity law: @(m >>= f) >>= g == m >>= (\\x -> f x >>= g)@.+--+-- >>> let f x = Valuation [x] (show x) :: Valuation [] Int String+-- >>> let g s = Valuation [length s] s+-- >>> lawMonadAssociativity (Valuation [0] (42 :: Int)) f g+-- True+--+-- >>> let f x = Valuation [1] (x * 2) :: Valuation [] Int Int+-- >>> let g x = Valuation [2] (x + 1)+-- >>> lawMonadAssociativity (Valuation [0] 10 :: Valuation [] Int Int) f g+-- True+lawMonadAssociativity :: (Eq (set var), Eq c, Monoid (set var)) => Valuation set var a -> (a -> Valuation set var b) -> (b -> Valuation set var c) -> Bool+lawMonadAssociativity m f g =+  ((m >>= f) >>= g) == (m >>= (\x -> f x >>= g))++-- | Comonad left identity law: @extract (duplicate v) == v@.+--+-- >>> lawComonadExtractDuplicate (Valuation [1,2] "hello" :: Valuation [] Int String)+-- True+--+-- >>> lawComonadExtractDuplicate (Valuation [] (42 :: Int) :: Valuation [] Int Int)+-- True+lawComonadExtractDuplicate :: (Eq (set var), Eq a) => Valuation set var a -> Bool+lawComonadExtractDuplicate v =+  extract (duplicate v) == v++-- | Comonad right identity law: @fmap extract (duplicate v) == v@.+--+-- >>> lawComonadDuplicateExtract (Valuation [1,2] "hello" :: Valuation [] Int String)+-- True+--+-- >>> lawComonadDuplicateExtract (Valuation [1] (42 :: Int) :: Valuation [] Int Int)+-- True+lawComonadDuplicateExtract :: (Eq (set var), Eq a) => Valuation set var a -> Bool+lawComonadDuplicateExtract v =+  fmap extract (duplicate v) == v++-- | Comonad associativity law: @duplicate (duplicate v) == fmap duplicate (duplicate v)@.+--+-- >>> lawComonadAssociativity (Valuation [1,2] "hello" :: Valuation [] Int String)+-- True+--+-- >>> lawComonadAssociativity (Valuation [1] (42 :: Int) :: Valuation [] Int Int)+-- True+lawComonadAssociativity :: (Eq (set var), Eq a) => Valuation set var a -> Bool+lawComonadAssociativity v =+  duplicate (duplicate v) == fmap duplicate (duplicate v)++-- | Bifunctor identity law: @bimap id id v == v@.+--+-- >>> lawBifunctorIdentity (Valuation [1,2,3] "hello" :: Valuation [] Int String)+-- True+--+-- >>> lawBifunctorIdentity (Valuation [1] (42 :: Int) :: Valuation [] Int Int)+-- True+lawBifunctorIdentity :: (Functor set, Eq (set var), Eq a) => Valuation set var a -> Bool+lawBifunctorIdentity v =+  bimap id id v == v++-- | Bifunctor composition law:+-- @bimap f1 g1 (bimap f2 g2 v) == bimap (f1 . f2) (g1 . g2) v@.+--+-- >>> lawBifunctorComposition (*2) length (+1) show (Valuation [1,2,3] (42 :: Int) :: Valuation [] Int Int)+-- True+--+-- >>> lawBifunctorComposition negate reverse (+1) (:[]) (Valuation [1,2] 'a' :: Valuation [] Int Char)+-- True+lawBifunctorComposition ::+  (Functor set, Eq (set var''), Eq c) =>+  (var' -> var'') ->+  (b -> c) ->+  (var -> var') ->+  (a -> b) ->+  Valuation set var a ->+  Bool+lawBifunctorComposition f1 g1 f2 g2 v =+  bimap f1 g1 (bimap f2 g2 v) == bimap (f1 . f2) (g1 . g2) v++-- | Associativity of 'combineVar': given two 'Semigroup''s,+-- @combineVar sd sv (combineVar sd sv a b) c == combineVar sd sv a (combineVar sd sv b c)@.+--+-- >>> import qualified Data.Valuation.Semigroup as S+-- >>> let a = Valuation [1] 10 :: Valuation [] Int Int+-- >>> let b = Valuation [2] 20+-- >>> let c = Valuation [3] 30+-- >>> lawCombineVarAssociative S.list S.sum a b c+-- True+--+-- >>> import qualified Data.Valuation.Semigroup as S+-- >>> let a = Valuation [1] 2 :: Valuation [] Int Int+-- >>> let b = Valuation [2] 3+-- >>> let c = Valuation [3] 4+-- >>> lawCombineVarAssociative S.list S.product a b c+-- True+lawCombineVarAssociative ::+  (Eq (set var), Eq v) =>+  Semigroup' (set var) ->+  Semigroup' v ->+  Valuation set var v ->+  Valuation set var v ->+  Valuation set var v ->+  Bool+lawCombineVarAssociative sd sv a b c =+  combineVar sd sv (combineVar sd sv a b) c == combineVar sd sv a (combineVar sd sv b c)++-- | Commutativity of 'combineVar': given two commutative 'Semigroup''s,+-- @combineVar sd sv a b == combineVar sd sv b a@.+--+-- The caller should ensure the semigroups are commutative; this function+-- tests whether the property holds for the given inputs.+--+-- >>> import qualified Data.Valuation.Semigroup as S+-- >>> let a = Valuation [1] 10 :: Valuation [] Int Int+-- >>> let b = Valuation [2] 20+-- >>> lawCombineVarCommutative S.list S.sum a b+-- False+--+-- >>> import qualified Data.Valuation.Semigroup as S+-- >>> import qualified Data.Set as Set+-- >>> let a = Valuation (Set.fromList [1]) 10 :: Valuation Set Int Int+-- >>> let b = Valuation (Set.fromList [2]) 20+-- >>> lawCombineVarCommutative (review applySemigroup Set.union) S.sum a b+-- True+lawCombineVarCommutative ::+  (Eq (set var), Eq v) =>+  Semigroup' (set var) ->+  Semigroup' v ->+  Valuation set var v ->+  Valuation set var v ->+  Bool+lawCombineVarCommutative sd sv a b =+  combineVar sd sv a b == combineVar sd sv b a
src/Data/Valuation/ValuationAlgebra.hs view
@@ -7,6 +7,7 @@   ( ValuationAlgebra (..),     ValuationAlgebra',     SetValuationAlgebra,+    SetValuationAlgebra',      -- * optics     HasValuationAlgebra (..),@@ -47,7 +48,7 @@ -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + sum s))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp sum) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int [] Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp sum) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int [] Int -- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = va -- >>> runSemigroup sg 3 4 -- 7@@ -57,44 +58,44 @@ -- 6 -- >>> z [1,2,3] -- 0-data ValuationAlgebra p v set var+data ValuationAlgebra p q r v set var   = ValuationAlgebra-      (SemiValuationAlgebra p v set var)+      (SemiValuationAlgebra p q r v set var)       -- | algebra unit       (ValuationAlgebraOp p set var v)       -- | algebra zero       (ValuationAlgebraOp p set var v)  type ValuationAlgebra' v set var =-  ValuationAlgebra (->) v set var+  ValuationAlgebra (->) (->) (->) v set var  -- | Classy lens for types that contain a 'ValuationAlgebra'.-class HasValuationAlgebra c p v set var | c -> p v set var where-  valuationAlgebra :: Lens' c (ValuationAlgebra p v set var)+class HasValuationAlgebra c p q r v set var | c -> p q r v set var where+  valuationAlgebra :: Lens' c (ValuationAlgebra p q r v set var)   valuationAlgebraUnit :: Lens' c (ValuationAlgebraOp p set var v)   valuationAlgebraUnit = valuationAlgebra . valuationAlgebraUnit   valuationAlgebraZero :: Lens' c (ValuationAlgebraOp p set var v)   valuationAlgebraZero = valuationAlgebra . valuationAlgebraZero -instance HasValuationAlgebra (ValuationAlgebra p v set var) p v set var where+instance HasValuationAlgebra (ValuationAlgebra p q r v set var) p q r v set var where   valuationAlgebra = id   valuationAlgebraUnit f (ValuationAlgebra s u z) = fmap (\u' -> ValuationAlgebra s u' z) (f u)   valuationAlgebraZero f (ValuationAlgebra s u z) = fmap (ValuationAlgebra s u) (f z)  -- | Classy prism for types that can be constructed from a 'ValuationAlgebra'.-class AsValuationAlgebra c p v set var | c -> p v set var where-  _ValuationAlgebra :: Prism' c (ValuationAlgebra p v set var)+class AsValuationAlgebra c p q r v set var | c -> p q r v set var where+  _ValuationAlgebra :: Prism' c (ValuationAlgebra p q r v set var) -instance AsValuationAlgebra (ValuationAlgebra p v set var) p v set var where+instance AsValuationAlgebra (ValuationAlgebra p q r v set var) p q r v set var where   _ValuationAlgebra = id -instance HasSemiValuationAlgebra (ValuationAlgebra p v set var) p v set var where+instance HasSemiValuationAlgebra (ValuationAlgebra p q r v set var) p q r v set var where   semiValuationAlgebra f (ValuationAlgebra a u z) = fmap (\a' -> ValuationAlgebra a' u z) (f a) -instance HasSemigroup (ValuationAlgebra p v set var) p v where+instance HasSemigroup (ValuationAlgebra p q r v set var) p v where   semigroup = semiValuationAlgebra . semigroup -instance HasProjectValuation (ValuationAlgebra p v set var) p v set var where+instance HasProjectValuation (ValuationAlgebra p q r v set var) q r v set var where   projectValuation = semiValuationAlgebra . projectValuation  -- |@@ -105,7 +106,7 @@ -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup) -- >>> let sva = SemiValuationAlgebra (review applySemigroup (+)) (ProjectValuation (\s v -> v + sum s))--- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp sum) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) Int [] Int+-- >>> let va = ValuationAlgebra sva (ValuationAlgebraOp sum) (ValuationAlgebraOp (const 0)) :: ValuationAlgebra (->) (->) (->) Int [] Int -- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = contramap (*2) va -- >>> runSemigroup sg 3 4 -- 7@@ -115,7 +116,7 @@ -- 12 -- >>> z [1,2,3] -- 0-instance (Profunctor p, Functor set) => Contravariant (ValuationAlgebra p v set) where+instance (Profunctor p, Profunctor q, Functor set) => Contravariant (ValuationAlgebra p q r v set) where   contramap f (ValuationAlgebra s (ValuationAlgebraOp u) (ValuationAlgebraOp z)) =     ValuationAlgebra (contramap f s) (ValuationAlgebraOp (lmap (fmap f) u)) (ValuationAlgebraOp (lmap (fmap f) z)) @@ -126,7 +127,7 @@ -- >>> import Data.Valuation.ValuationAlgebraOp (ValuationAlgebraOp(..)) -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup)--- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = conquer :: ValuationAlgebra (->) [Int] [] Int+-- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = conquer :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> p [10,20] [42]@@ -143,9 +144,9 @@ -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup) -- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s))--- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s))--- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = divide (\x -> (x, x + 10)) va1 va2 -- >>> runSemigroup sg [1] [2] -- [1,2]@@ -153,7 +154,7 @@ -- [1,2,3,13,12,11] -- >>> z [1,2,3] -- [-1,-2,-3]-instance (Functor set, Strong p, Arrow p, Prelude.Semigroup v, Prelude.Monoid v) => Divisible (ValuationAlgebra p v set) where+instance (Functor set, Strong p, Strong q, Arrow p, Category q, Category r, Prelude.Semigroup v, Prelude.Monoid v) => Divisible (ValuationAlgebra p q r v set) where   conquer = ValuationAlgebra conquer (ValuationAlgebraOp (rmap (const mempty) id)) (ValuationAlgebraOp (rmap (const mempty) id))   divide f (ValuationAlgebra s1 (ValuationAlgebraOp u1) (ValuationAlgebraOp z1)) (ValuationAlgebra s2 (ValuationAlgebraOp u2) (ValuationAlgebraOp z2)) =     let combine g1 g2 =@@ -170,7 +171,7 @@ -- >>> import Data.Valuation.ValuationAlgebraOp (ValuationAlgebraOp(..)) -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup)--- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = lose absurd :: ValuationAlgebra (->) [Int] [] Void+-- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = lose absurd :: ValuationAlgebra (->) (->) (->) [Int] [] Void -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> p [] [42]@@ -187,9 +188,9 @@ -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup) -- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s))--- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s))--- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = choose (\x -> if even x then Left x else Right x) va1 va2 -- >>> runSemigroup sg [1] [2] -- [1,2]@@ -197,7 +198,7 @@ -- [2,4,3,1] -- >>> z [1,2,3,4] -- [-2,-4]-instance (Filterable set, Strong p, Arrow p, Prelude.Semigroup v, Prelude.Monoid v) => Decidable (ValuationAlgebra p v set) where+instance (Filterable set, Strong p, Strong q, Arrow p, Category q, Category r, Prelude.Semigroup v, Prelude.Monoid v) => Decidable (ValuationAlgebra p q r v set) where   lose f = ValuationAlgebra (lose f) (ValuationAlgebraOp (rmap (const mempty) id)) (ValuationAlgebraOp (rmap (const mempty) id))   choose ch (ValuationAlgebra s1 (ValuationAlgebraOp u1) (ValuationAlgebraOp z1)) (ValuationAlgebra s2 (ValuationAlgebraOp u2) (ValuationAlgebraOp z2)) =     let lefts = mapMaybe (either Just (const Nothing) . ch)@@ -216,9 +217,9 @@ -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup) -- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s))--- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s))--- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = divise (\x -> (x, x + 10)) va1 va2 -- >>> runSemigroup sg [1] [2] -- [1,2]@@ -226,7 +227,7 @@ -- [1,2,3,13,12,11] -- >>> z [1,2,3] -- [-1,-2,-3]-instance (Functor set, Strong p, Semigroupoid p, Prelude.Semigroup v) => Divise (ValuationAlgebra p v set) where+instance (Functor set, Strong p, Semigroupoid p, Strong q, Semigroupoid q, Semigroupoid r, Prelude.Semigroup v) => Divise (ValuationAlgebra p q r v set) where   divise f (ValuationAlgebra s1 (ValuationAlgebraOp u1) (ValuationAlgebraOp z1)) (ValuationAlgebra s2 (ValuationAlgebraOp u2) (ValuationAlgebraOp z2)) =     let combine g1 g2 =           let g1' = lmap (fmap (fst . f)) g1@@ -242,9 +243,9 @@ -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup) -- >>> let sva1 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ s))--- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va1 = ValuationAlgebra sva1 (ValuationAlgebraOp id) (ValuationAlgebraOp (map negate)) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let sva2 = SemiValuationAlgebra (review applySemigroup (++)) (ProjectValuation (\s v -> v ++ reverse s))--- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) [Int] [] Int+-- >>> let va2 = ValuationAlgebra sva2 (ValuationAlgebraOp reverse) (ValuationAlgebraOp (const [])) :: ValuationAlgebra (->) (->) (->) [Int] [] Int -- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = decide (\x -> if even x then Left x else Right x) va1 va2 -- >>> runSemigroup sg [1] [2] -- [1,2]@@ -252,7 +253,7 @@ -- [2,4,3,1] -- >>> z [1,2,3,4] -- [-2,-4]-instance (Filterable set, Strong p, Semigroupoid p, Prelude.Semigroup v) => Decide (ValuationAlgebra p v set) where+instance (Filterable set, Strong p, Semigroupoid p, Strong q, Semigroupoid q, Semigroupoid r, Prelude.Semigroup v) => Decide (ValuationAlgebra p q r v set) where   decide ch (ValuationAlgebra s1 (ValuationAlgebraOp u1) (ValuationAlgebraOp z1)) (ValuationAlgebra s2 (ValuationAlgebraOp u2) (ValuationAlgebraOp z2)) =     let lefts = mapMaybe (either Just (const Nothing) . ch)         rights = mapMaybe (either (const Nothing) Just . ch)@@ -270,16 +271,19 @@ -- >>> import Data.Valuation.ValuationAlgebraOp (ValuationAlgebraOp(..)) -- >>> import Control.Lens (review) -- >>> import Data.Valuation.Semigroup (Semigroup, applySemigroup, runSemigroup)--- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = conclude absurd :: ValuationAlgebra (->) [Int] [] Void+-- >>> let ValuationAlgebra (SemiValuationAlgebra sg (ProjectValuation p)) (ValuationAlgebraOp u) (ValuationAlgebraOp z) = conclude absurd :: ValuationAlgebra (->) (->) (->) [Int] [] Void -- >>> runSemigroup sg [1] [2] -- [1,2] -- >>> u [] -- [] -- >>> z [] -- []-instance (Filterable set, Strong p, Semigroupoid p, Arrow p, Prelude.Semigroup v, Prelude.Monoid v) => Conclude (ValuationAlgebra p v set) where+instance (Filterable set, Strong p, Semigroupoid p, Arrow p, Strong q, Semigroupoid q, Category q, Semigroupoid r, Category r, Prelude.Semigroup v, Prelude.Monoid v) => Conclude (ValuationAlgebra p q r v set) where   conclude f = ValuationAlgebra (conclude f) (ValuationAlgebraOp (rmap (const mempty) id)) (ValuationAlgebraOp (rmap (const mempty) id))  -- | A 'ValuationAlgebra' specialised to 'Set'.-type SetValuationAlgebra p v var =-  ValuationAlgebra p v Set var+type SetValuationAlgebra p q r v var =+  ValuationAlgebra p q r v Set var++type SetValuationAlgebra' v var =+  SetValuationAlgebra (->) (->) (->) v var
src/Data/Valuation/ValuationAlgebraOp.hs view
@@ -92,7 +92,7 @@   _ValuationAlgebraOp = Prelude.id  -- | Iso between a 'ValuationAlgebraOp' producing an endomorphism and a 'ProjectValuation'.-valuationAlgebraOpProjectValuation :: Iso (ValuationAlgebraOp p set var (p v v)) (ValuationAlgebraOp p' set' var' (p' v' v')) (ProjectValuation p v set var) (ProjectValuation p' v' set' var')+valuationAlgebraOpProjectValuation :: Iso (ValuationAlgebraOp p set var (q v v)) (ValuationAlgebraOp p' set' var' (q' v' v')) (ProjectValuation p q v set var) (ProjectValuation p' q' v' set' var') valuationAlgebraOpProjectValuation =   iso     (\(ValuationAlgebraOp k) -> ProjectValuation k)
+ test/Main.hs view
@@ -0,0 +1,15 @@+{-# OPTIONS_GHC -Wall -Werror -Wno-orphans #-}++module Main where++import System.Exit (exitWith)+import System.Process (rawSystem)++main :: IO ()+main = exitWith =<< rawSystem "cabal"+  [ "repl"+  , "--with-compiler=doctest"+  , "--repl-options=-w"+  , "--repl-options=-Wdefault"+  , "lib:valuations"+  ]
valuations.cabal view
@@ -1,16 +1,16 @@+cabal-version:        2.4 name:                 valuations-version:              0.0.3+version:              0.0.4 synopsis:             Valuations description:          Valuations: Valuation and Valuation Algebra-license:              BSD3+license:              BSD-3-Clause license-file:         LICENCE author:               Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> maintainer:           Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ> copyright:            Copyright (C) 2026 Tony Morris-category:             Test+category:             Math build-type:           Simple-extra-source-files:   changelog.md-cabal-version:        >=1.10+extra-doc-files:      changelog.md homepage:             https://gitlab.com/tonymorris/valuations bug-reports:          https://gitlab.com/tonymorris/valuations/issues tested-with:          GHC == 9.6.7@@ -22,9 +22,11 @@ library   exposed-modules:                       Data.Valuation-                      Data.Valuation.BinaryFunction+                      Data.Valuation.CovariantFunctor                       Data.Valuation.DomainLattice                       Data.Valuation.PartialOrder+                      Data.Valuation.Poset+                      Data.Valuation.Presheaf                       Data.Valuation.PresheafValuationAlgebra                       Data.Valuation.ProjectValuation                       Data.Valuation.Semigroup@@ -51,4 +53,14 @@    default-language:   Haskell2010 +  ghc-options:        -Wall++test-suite doctest+  type:               exitcode-stdio-1.0+  hs-source-dirs:     test+  main-is:            Main.hs+  build-depends:      base >= 4.8 && < 6+                    , process >= 1 && < 2+  build-tool-depends: doctest:doctest >= 0.22+  default-language:   Haskell2010   ghc-options:        -Wall