{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
module Data.Semigroup.Quantale where
import Data.Connection hiding (floor', ceiling')
import Data.Connection.Yoneda
import Data.Float
import Data.Group
import Data.Prd
import Data.Prd.Lattice
import Data.Word
import Data.Semigroup.Orphan ()
import Prelude hiding (negate, until, filter)
import Test.Property.Util ((<==>),(==>))
import qualified Prelude as Pr
residuated :: Quantale a => a -> a -> a -> Bool
residuated x y z = x <> y <~ z <==> y <~ x \\ z <==> x <~ z // y
class (Semigroup a, Prd a) => Quantale a where
residr :: a -> Conn a a
residr x = Conn (x<>) (x\\)
residl :: a -> Conn a a
residl x = Conn (<>x) (//x)
(\\) :: a -> a -> a
x \\ y = connr (residr x) y
(//) :: a -> a -> a
x // y = connl (residl x) y
instance Quantale Float where
x \\ y = y // x
y // x | y =~ x = 0
| otherwise = let z = y - x in if z + x <~ y then upper' z (x<>) y else lower' z (x<>) y
lower' :: Prd a => Float -> (Float -> a) -> a -> Float
lower' z f x = until (\y -> f y <~ x) ge (shift $ -1) z
upper' :: Prd a => Float -> (Float -> a) -> a -> Float
upper' z g y = while (\x -> g x <~ y) le (shift 1) z
incBy :: Yoneda a => Quantale a => a -> Rep a -> Rep a
incBy x = connl filter . (x <>) . connr filter
decBy :: Yoneda a => Quantale a => a -> Rep a -> Rep a
decBy x = connl filter . (x \\) . connr filter