{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-orphans #-}
#if __GLASGOW_HASKELL__ < 900
{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
{-# OPTIONS_GHC -Wno-unused-imports #-}
#endif
module Constrained.NumSpec where
import Constrained.Base
import Constrained.Conformance ()
import Constrained.Core (NonEmpty ((:|)), unionWithMaybe)
import Constrained.GenT (GenT, MonadGenError (..), pureGen, sizeT)
import Constrained.Generic
import Constrained.List
import Control.Applicative ((<|>))
import Control.Arrow (first)
import Data.Kind
import Data.List (nub)
import qualified Data.List.NonEmpty as NE
import Data.Maybe (fromJust, mapMaybe)
import qualified Data.Set as Set
import Data.Typeable (typeOf)
import Data.Word
import GHC.Int
import GHC.Natural
import GHC.Real
import GHC.TypeLits
import System.Random.Stateful (Random (..), Uniform (..))
import Test.QuickCheck (Arbitrary (arbitrary, shrink), choose, frequency)
data NumOrdW (sym :: Symbol) (dom :: [Type]) (rng :: Type) where
LessOrEqualW :: OrdLike a => NumOrdW "<=." '[a, a] Bool
LessW :: OrdLike a => NumOrdW "<." '[a, a] Bool
GreaterOrEqualW :: OrdLike a => NumOrdW ">=." '[a, a] Bool
GreaterW :: OrdLike a => NumOrdW ">." '[a, a] Bool
deriving instance Eq (NumOrdW s ds r)
instance Show (NumOrdW s ds r) where
show :: NumOrdW s ds r -> String
show NumOrdW s ds r
LessOrEqualW = String
"<=."
show NumOrdW s ds r
LessW = String
"<."
show NumOrdW s ds r
GreaterOrEqualW = String
">=."
show NumOrdW s ds r
GreaterW = String
">."
instance Semantics NumOrdW where
semantics :: forall (s :: Symbol) (d :: [*]) r. NumOrdW s d r -> FunTy d r
semantics NumOrdW s d r
LessOrEqualW = forall a. Ord a => a -> a -> Bool
(<=)
semantics NumOrdW s d r
LessW = forall a. Ord a => a -> a -> Bool
(<)
semantics NumOrdW s d r
GreaterW = forall a. Ord a => a -> a -> Bool
(>)
semantics NumOrdW s d r
GreaterOrEqualW = forall a. Ord a => a -> a -> Bool
(>=)
instance Syntax NumOrdW where
isInFix :: forall (s :: Symbol) (dom :: [*]) rng. NumOrdW s dom rng -> Bool
isInFix NumOrdW s dom rng
LessOrEqualW = Bool
True
isInFix NumOrdW s dom rng
LessW = Bool
True
isInFix NumOrdW s dom rng
GreaterOrEqualW = Bool
True
isInFix NumOrdW s dom rng
GreaterW = Bool
True
class (Ord a, HasSpec a) => OrdLike a where
leqSpec :: a -> Specification a
default leqSpec ::
( TypeSpec a ~ TypeSpec (SimpleRep a)
, HasSimpleRep a
, OrdLike (SimpleRep a)
) =>
a ->
Specification a
leqSpec = forall a.
(HasSpec a, HasSimpleRep a, TypeSpec a ~ TypeSpec (SimpleRep a)) =>
Specification (SimpleRep a) -> Specification a
fromSimpleRepSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. OrdLike a => a -> Specification a
leqSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep
ltSpec :: a -> Specification a
default ltSpec ::
( TypeSpec a ~ TypeSpec (SimpleRep a)
, HasSimpleRep a
, OrdLike (SimpleRep a)
) =>
a ->
Specification a
ltSpec = forall a.
(HasSpec a, HasSimpleRep a, TypeSpec a ~ TypeSpec (SimpleRep a)) =>
Specification (SimpleRep a) -> Specification a
fromSimpleRepSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. OrdLike a => a -> Specification a
ltSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep
geqSpec :: a -> Specification a
default geqSpec ::
( TypeSpec a ~ TypeSpec (SimpleRep a)
, HasSimpleRep a
, OrdLike (SimpleRep a)
) =>
a ->
Specification a
geqSpec = forall a.
(HasSpec a, HasSimpleRep a, TypeSpec a ~ TypeSpec (SimpleRep a)) =>
Specification (SimpleRep a) -> Specification a
fromSimpleRepSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. OrdLike a => a -> Specification a
geqSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep
gtSpec :: a -> Specification a
default gtSpec ::
( TypeSpec a ~ TypeSpec (SimpleRep a)
, HasSimpleRep a
, OrdLike (SimpleRep a)
) =>
a ->
Specification a
gtSpec = forall a.
(HasSpec a, HasSimpleRep a, TypeSpec a ~ TypeSpec (SimpleRep a)) =>
Specification (SimpleRep a) -> Specification a
fromSimpleRepSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. OrdLike a => a -> Specification a
gtSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep
instance {-# OVERLAPPABLE #-} (Ord a, HasSpec a, MaybeBounded a, Num a, TypeSpec a ~ NumSpec a) => OrdLike a where
leqSpec :: a -> Specification a
leqSpec a
l = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just a
l)
ltSpec :: a -> Specification a
ltSpec a
l
| Just a
b <- forall a. MaybeBounded a => Maybe a
lowerBound
, a
l forall a. Eq a => a -> a -> Bool
== a
b =
forall a. NonEmpty String -> Specification a
ErrorSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
"ltSpec @" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall a. Typeable a => a -> TypeRep
typeOf a
l) forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
l))
| Bool
otherwise = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval forall a. Maybe a
Nothing (forall a. a -> Maybe a
Just (a
l forall a. Num a => a -> a -> a
- a
1))
geqSpec :: a -> Specification a
geqSpec a
l = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. a -> Maybe a
Just a
l) forall a. Maybe a
Nothing
gtSpec :: a -> Specification a
gtSpec a
l
| Just a
b <- forall a. MaybeBounded a => Maybe a
upperBound
, a
l forall a. Eq a => a -> a -> Bool
== a
b =
forall a. NonEmpty String -> Specification a
ErrorSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
"gtSpec @" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall a. Typeable a => a -> TypeRep
typeOf a
l) forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
l))
| Bool
otherwise = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. a -> Maybe a
Just (a
l forall a. Num a => a -> a -> a
+ a
1)) forall a. Maybe a
Nothing
class MaybeBounded a where
lowerBound :: Maybe a
upperBound :: Maybe a
default lowerBound :: Bounded a => Maybe a
lowerBound = forall a. a -> Maybe a
Just forall a. Bounded a => a
minBound
default upperBound :: Bounded a => Maybe a
upperBound = forall a. a -> Maybe a
Just forall a. Bounded a => a
maxBound
instance MaybeBounded Int
instance MaybeBounded Int64
instance MaybeBounded Int32
instance MaybeBounded Int16
instance MaybeBounded Int8
instance MaybeBounded Word64
instance MaybeBounded Word32
instance MaybeBounded Word16
instance MaybeBounded Word8
instance MaybeBounded Integer where
lowerBound :: Maybe Integer
lowerBound = forall a. Maybe a
Nothing
upperBound :: Maybe Integer
upperBound = forall a. Maybe a
Nothing
instance MaybeBounded (Ratio Integer) where
lowerBound :: Maybe (Ratio Integer)
lowerBound = forall a. Maybe a
Nothing
upperBound :: Maybe (Ratio Integer)
upperBound = forall a. Maybe a
Nothing
instance MaybeBounded Natural where
lowerBound :: Maybe Natural
lowerBound = forall a. a -> Maybe a
Just Natural
0
upperBound :: Maybe Natural
upperBound = forall a. Maybe a
Nothing
instance MaybeBounded Float where
lowerBound :: Maybe Float
lowerBound = forall a. Maybe a
Nothing
upperBound :: Maybe Float
upperBound = forall a. Maybe a
Nothing
data NumSpec n = NumSpecInterval (Maybe n) (Maybe n)
instance Ord n => Eq (NumSpec n) where
NumSpecInterval Maybe n
ml Maybe n
mh == :: NumSpec n -> NumSpec n -> Bool
== NumSpecInterval Maybe n
ml' Maybe n
mh'
| forall {a}. Ord a => Maybe a -> Maybe a -> Bool
isEmpty Maybe n
ml Maybe n
mh = forall {a}. Ord a => Maybe a -> Maybe a -> Bool
isEmpty Maybe n
ml' Maybe n
mh'
| forall {a}. Ord a => Maybe a -> Maybe a -> Bool
isEmpty Maybe n
ml' Maybe n
mh' = forall {a}. Ord a => Maybe a -> Maybe a -> Bool
isEmpty Maybe n
ml Maybe n
mh
| Bool
otherwise = Maybe n
ml forall a. Eq a => a -> a -> Bool
== Maybe n
ml' Bool -> Bool -> Bool
&& Maybe n
mh forall a. Eq a => a -> a -> Bool
== Maybe n
mh'
where
isEmpty :: Maybe a -> Maybe a -> Bool
isEmpty (Just a
a) (Just a
b) = a
a forall a. Ord a => a -> a -> Bool
> a
b
isEmpty Maybe a
_ Maybe a
_ = Bool
False
instance Show n => Show (NumSpec n) where
show :: NumSpec n -> String
show (NumSpecInterval Maybe n
ml Maybe n
mu) = String
lb forall a. [a] -> [a] -> [a]
++ String
".." forall a. [a] -> [a] -> [a]
++ String
ub
where
lb :: String
lb = String
"[" forall a. [a] -> [a] -> [a]
++ forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" forall a. Show a => a -> String
show Maybe n
ml
ub :: String
ub = forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" forall a. Show a => a -> String
show Maybe n
mu forall a. [a] -> [a] -> [a]
++ String
"]"
instance Ord n => Semigroup (NumSpec n) where
NumSpecInterval Maybe n
ml Maybe n
mu <> :: NumSpec n -> NumSpec n -> NumSpec n
<> NumSpecInterval Maybe n
ml' Maybe n
mu' =
forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval
(forall a. (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
unionWithMaybe forall a. Ord a => a -> a -> a
max Maybe n
ml Maybe n
ml')
(forall a. (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
unionWithMaybe forall a. Ord a => a -> a -> a
min Maybe n
mu Maybe n
mu')
instance Ord n => Monoid (NumSpec n) where
mempty :: NumSpec n
mempty = forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval forall a. Maybe a
Nothing forall a. Maybe a
Nothing
instance (Arbitrary a, Ord a) => Arbitrary (NumSpec a) where
arbitrary :: Gen (NumSpec a)
arbitrary = do
Maybe a
m <- forall a. Arbitrary a => Gen a
arbitrary
Maybe a
m' <- forall a. Arbitrary a => Gen a
arbitrary
forall a. HasCallStack => [(Int, Gen a)] -> Gen a
frequency [(Int
10, forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall {n}. Ord n => Maybe n -> Maybe n -> NumSpec n
mkLoHiInterval Maybe a
m Maybe a
m'), (Int
1, forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval Maybe a
m Maybe a
m')]
where
mkLoHiInterval :: Maybe n -> Maybe n -> NumSpec n
mkLoHiInterval (Just n
a) (Just n
b) = forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> a -> a
min n
a n
b) (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> a -> a
max n
a n
b)
mkLoHiInterval Maybe n
m Maybe n
m' = forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval Maybe n
m Maybe n
m'
shrink :: NumSpec a -> [NumSpec a]
shrink (NumSpecInterval Maybe a
m Maybe a
m') =
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => a -> [a]
shrink (Maybe a
m, Maybe a
m')
instance Arbitrary Natural where
arbitrary :: Gen Natural
arbitrary = Word -> Natural
wordToNatural forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Arbitrary a => Gen a
arbitrary
shrink :: Natural -> [Natural]
shrink Natural
n = [Word -> Natural
wordToNatural Word
w | Word
w <- forall a. Arbitrary a => a -> [a]
shrink (Natural -> Word
naturalToWord Natural
n)]
instance Uniform Natural where
uniformM :: forall g (m :: * -> *). StatefulGen g m => g -> m Natural
uniformM g
g = Word -> Natural
wordToNatural forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a g (m :: * -> *). (Uniform a, StatefulGen g m) => g -> m a
uniformM g
g
instance Random Natural where
randomR :: forall g. RandomGen g => (Natural, Natural) -> g -> (Natural, g)
randomR (Natural
lo, Natural
hi) g
g = forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (forall a. Integral a => a -> Integer
toInteger Natural
lo, forall a. Integral a => a -> Integer
toInteger Natural
hi) g
g
instance Random (Ratio Integer) where
randomR :: forall g.
RandomGen g =>
(Ratio Integer, Ratio Integer) -> g -> (Ratio Integer, g)
randomR (Ratio Integer
lo, Ratio Integer
hi) g
g =
let (Ratio Integer
r, g
g') = forall a g. (Random a, RandomGen g) => g -> (a, g)
random g
g
in (Ratio Integer
lo forall a. Num a => a -> a -> a
+ (Ratio Integer
hi forall a. Num a => a -> a -> a
- Ratio Integer
lo) forall a. Num a => a -> a -> a
* Ratio Integer
r, g
g')
random :: forall g. RandomGen g => g -> (Ratio Integer, g)
random g
g =
let (Integer
d, g
g') = forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first ((forall a. Num a => a -> a -> a
+ Integer
1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a
abs) forall a b. (a -> b) -> a -> b
$ forall a g. (Random a, RandomGen g) => g -> (a, g)
random g
g
(Integer
n, g
g'') = forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (Integer
0, Integer
d) g
g'
in (Integer
n forall a. Integral a => a -> a -> Ratio a
% Integer
d, g
g'')
emptyNumSpec :: Ord a => NumSpec a
emptyNumSpec :: forall n. Ord n => NumSpec n
emptyNumSpec = forall a. Monoid a => a
mempty
guardNumSpec ::
(Ord n, HasSpec n, TypeSpec n ~ NumSpec n) =>
[String] -> NumSpec n -> Specification n
guardNumSpec :: forall n.
(Ord n, HasSpec n, TypeSpec n ~ NumSpec n) =>
[String] -> NumSpec n -> Specification n
guardNumSpec [String]
msg s :: NumSpec n
s@(NumSpecInterval (Just n
a) (Just n
b))
| n
a forall a. Ord a => a -> a -> Bool
> n
b = forall a. NonEmpty String -> Specification a
ErrorSpec (String
"NumSpec has low bound greater than hi bound" forall a. a -> [a] -> NonEmpty a
:| ((String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show NumSpec n
s) forall a. a -> [a] -> [a]
: [String]
msg))
| n
a forall a. Eq a => a -> a -> Bool
== n
b = forall a. a -> Specification a
equalSpec n
a
guardNumSpec [String]
_ NumSpec n
s = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec NumSpec n
s
combineNumSpec ::
(HasSpec n, Ord n, TypeSpec n ~ NumSpec n) =>
NumSpec n ->
NumSpec n ->
Specification n
combineNumSpec :: forall n.
(HasSpec n, Ord n, TypeSpec n ~ NumSpec n) =>
NumSpec n -> NumSpec n -> Specification n
combineNumSpec NumSpec n
s NumSpec n
s' = forall n.
(Ord n, HasSpec n, TypeSpec n ~ NumSpec n) =>
[String] -> NumSpec n -> Specification n
guardNumSpec [String
"when combining two NumSpecs", String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show NumSpec n
s, String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show NumSpec n
s'] (NumSpec n
s forall a. Semigroup a => a -> a -> a
<> NumSpec n
s')
genFromNumSpec ::
(MonadGenError m, Show n, Random n, Ord n, Num n, MaybeBounded n) =>
NumSpec n ->
GenT m n
genFromNumSpec :: forall (m :: * -> *) n.
(MonadGenError m, Show n, Random n, Ord n, Num n,
MaybeBounded n) =>
NumSpec n -> GenT m n
genFromNumSpec (NumSpecInterval Maybe n
ml Maybe n
mu) = do
Int
n <- forall (m :: * -> *). Monad m => GenT m Int
sizeT
forall (m :: * -> *) a. Applicative m => Gen a -> GenT m a
pureGen forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Random a => (a, a) -> Gen a
choose forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (m :: * -> *) a.
(MonadGenError m, Ord a, Num a, Show a) =>
Maybe a -> Maybe a -> Integer -> m (a, a)
constrainInterval (Maybe n
ml forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. MaybeBounded a => Maybe a
lowerBound) (Maybe n
mu forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall a. MaybeBounded a => Maybe a
upperBound) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)
shrinkWithNumSpec :: Arbitrary n => NumSpec n -> n -> [n]
shrinkWithNumSpec :: forall n. Arbitrary n => NumSpec n -> n -> [n]
shrinkWithNumSpec NumSpec n
_ = forall a. Arbitrary a => a -> [a]
shrink
constrainInterval ::
(MonadGenError m, Ord a, Num a, Show a) => Maybe a -> Maybe a -> Integer -> m (a, a)
constrainInterval :: forall (m :: * -> *) a.
(MonadGenError m, Ord a, Num a, Show a) =>
Maybe a -> Maybe a -> Integer -> m (a, a)
constrainInterval Maybe a
ml Maybe a
mu Integer
r =
case (Maybe a
ml, Maybe a
mu) of
(Maybe a
Nothing, Maybe a
Nothing) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (-a
r', a
r')
(Just a
l, Maybe a
Nothing)
| a
l forall a. Ord a => a -> a -> Bool
< a
0 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Ord a => a -> a -> a
max a
l (forall a. Num a => a -> a
negate a
r'), a
r')
| Bool
otherwise -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
l, a
l forall a. Num a => a -> a -> a
+ a
2 forall a. Num a => a -> a -> a
* a
r')
(Maybe a
Nothing, Just a
u)
| a
u forall a. Ord a => a -> a -> Bool
> a
0 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Num a => a -> a
negate a
r', forall a. Ord a => a -> a -> a
min a
u a
r')
| Bool
otherwise -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
u forall a. Num a => a -> a -> a
- a
r' forall a. Num a => a -> a -> a
- a
r', a
u)
(Just a
l, Just a
u)
| a
l forall a. Ord a => a -> a -> Bool
> a
u -> forall (m :: * -> *) a.
(MonadGenError m, HasCallStack) =>
NonEmpty String -> m a
genError (forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
"bad interval: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
l forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
u))
| a
u forall a. Ord a => a -> a -> Bool
< a
0 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall {p}. (Ord p, Num p) => p -> p -> p -> p
safeSub a
l (forall {p}. (Ord p, Num p) => p -> p -> p -> p
safeSub a
l a
u a
r') a
r', a
u)
| a
l forall a. Ord a => a -> a -> Bool
>= a
0 -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
l, forall {p}. (Ord p, Num p) => p -> p -> p -> p
safeAdd a
u (forall {p}. (Ord p, Num p) => p -> p -> p -> p
safeAdd a
u a
l a
r') a
r')
| Bool
otherwise -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Ord a => a -> a -> a
max a
l (-a
r'), forall a. Ord a => a -> a -> a
min a
u a
r')
where
r' :: a
r' = forall a. Num a => a -> a
abs forall a b. (a -> b) -> a -> b
$ forall a. Num a => Integer -> a
fromInteger Integer
r
safeSub :: p -> p -> p -> p
safeSub p
l p
a p
b
| p
a forall a. Num a => a -> a -> a
- p
b forall a. Ord a => a -> a -> Bool
> p
a = p
l
| Bool
otherwise = forall a. Ord a => a -> a -> a
max p
l (p
a forall a. Num a => a -> a -> a
- p
b)
safeAdd :: p -> p -> p -> p
safeAdd p
u p
a p
b
| p
a forall a. Num a => a -> a -> a
+ p
b forall a. Ord a => a -> a -> Bool
< p
a = p
u
| Bool
otherwise = forall a. Ord a => a -> a -> a
min p
u (p
a forall a. Num a => a -> a -> a
+ p
b)
conformsToNumSpec :: Ord n => n -> NumSpec n -> Bool
conformsToNumSpec :: forall n. Ord n => n -> NumSpec n -> Bool
conformsToNumSpec n
i (NumSpecInterval Maybe n
ml Maybe n
mu) = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (forall a. Ord a => a -> a -> Bool
<= n
i) Maybe n
ml Bool -> Bool -> Bool
&& forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (n
i forall a. Ord a => a -> a -> Bool
<=) Maybe n
mu
nubOrd :: Ord a => [a] -> [a]
nubOrd :: forall a. Ord a => [a] -> [a]
nubOrd =
forall {a}. Ord a => Set a -> [a] -> [a]
loop forall a. Monoid a => a
mempty
where
loop :: Set a -> [a] -> [a]
loop Set a
_ [] = []
loop Set a
s (a
a : [a]
as)
| a
a forall a. Ord a => a -> Set a -> Bool
`Set.member` Set a
s = Set a -> [a] -> [a]
loop Set a
s [a]
as
| Bool
otherwise =
let s' :: Set a
s' = forall a. Ord a => a -> Set a -> Set a
Set.insert a
a Set a
s in Set a
s' seq :: forall a b. a -> b -> b
`seq` a
a forall a. a -> [a] -> [a]
: Set a -> [a] -> [a]
loop Set a
s' [a]
as
nubOrdMemberSpec :: Ord a => String -> [a] -> Specification a
nubOrdMemberSpec :: forall a. Ord a => String -> [a] -> Specification a
nubOrdMemberSpec String
message [a]
xs =
forall a. [a] -> NonEmpty String -> Specification a
memberSpecList
(forall a. Ord a => [a] -> [a]
nubOrd [a]
xs)
( forall a. [a] -> NonEmpty a
NE.fromList
[ String
"In call to nubOrdMemberSpec"
, String
"Called from context"
, String
message
, String
"The input is the empty list."
]
)
lowBound :: Bounded n => Maybe n -> n
lowBound :: forall n. Bounded n => Maybe n -> n
lowBound Maybe n
Nothing = forall a. Bounded a => a
minBound
lowBound (Just n
n) = n
n
highBound :: Bounded n => Maybe n -> n
highBound :: forall n. Bounded n => Maybe n -> n
highBound Maybe n
Nothing = forall a. Bounded a => a
maxBound
highBound (Just n
n) = n
n
countSpec :: forall n. (Bounded n, Integral n) => NumSpec n -> Integer
countSpec :: forall n. (Bounded n, Integral n) => NumSpec n -> Integer
countSpec (NumSpecInterval Maybe n
lo Maybe n
hi) = if Maybe n
lo forall a. Ord a => a -> a -> Bool
> Maybe n
hi then Integer
0 else forall a. Integral a => a -> Integer
toInteger n
high forall a. Num a => a -> a -> a
- forall a. Integral a => a -> Integer
toInteger n
low forall a. Num a => a -> a -> a
+ Integer
1
where
high :: n
high = forall n. Bounded n => Maybe n -> n
highBound Maybe n
hi
low :: n
low = forall n. Bounded n => Maybe n -> n
lowBound Maybe n
lo
finiteSize :: forall n. (Integral n, Bounded n) => Integer
finiteSize :: forall n. (Integral n, Bounded n) => Integer
finiteSize = forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
maxBound @n) forall a. Num a => a -> a -> a
- forall a. Integral a => a -> Integer
toInteger (forall a. Bounded a => a
minBound @n) forall a. Num a => a -> a -> a
+ Integer
1
notInNumSpec ::
forall n.
( HasSpec n
, TypeSpec n ~ NumSpec n
, Bounded n
, Integral n
) =>
NumSpec n ->
[n] ->
Specification n
notInNumSpec :: forall n.
(HasSpec n, TypeSpec n ~ NumSpec n, Bounded n, Integral n) =>
NumSpec n -> [n] -> Specification n
notInNumSpec ns :: NumSpec n
ns@(NumSpecInterval Maybe n
a Maybe n
b) [n]
bad
| forall a. Integral a => a -> Integer
toInteger (forall (t :: * -> *) a. Foldable t => t a -> Int
length [n]
bad) forall a. Ord a => a -> a -> Bool
> (forall n. (Integral n, Bounded n) => Integer
finiteSize @n forall a. Integral a => a -> a -> a
`div` Integer
2) Bool -> Bool -> Bool
|| forall n. (Bounded n, Integral n) => NumSpec n -> Integer
countSpec NumSpec n
ns forall a. Ord a => a -> a -> Bool
< forall a. Integral a => a -> Integer
toInteger (forall (t :: * -> *) a. Foldable t => t a -> Int
length [n]
bad) =
forall a. Ord a => String -> [a] -> Specification a
nubOrdMemberSpec
(String
"call to: (notInNumSpec " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show NumSpec n
ns forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [n]
bad forall a. [a] -> [a] -> [a]
++ String
")")
[n
x | n
x <- [forall n. Bounded n => Maybe n -> n
lowBound Maybe n
a .. forall n. Bounded n => Maybe n -> n
highBound Maybe n
b], forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem n
x [n]
bad]
| Bool
otherwise = forall a. HasSpec a => TypeSpec a -> [a] -> Specification a
TypeSpec @n NumSpec n
ns [n]
bad
guardEmpty :: (Ord n, Num n) => Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty :: forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty (Just n
a) (Just n
b) NumSpec n
s
| n
a forall a. Ord a => a -> a -> Bool
<= n
b = NumSpec n
s
| Bool
otherwise = forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. a -> Maybe a
Just n
1) (forall a. a -> Maybe a
Just n
0)
guardEmpty Maybe n
_ Maybe n
_ NumSpec n
s = NumSpec n
s
addNumSpec :: (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
addNumSpec :: forall n. (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
addNumSpec (NumSpecInterval Maybe n
x Maybe n
y) (NumSpecInterval Maybe n
a Maybe n
b) =
forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty Maybe n
x Maybe n
y forall a b. (a -> b) -> a -> b
$
forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty Maybe n
a Maybe n
b forall a b. (a -> b) -> a -> b
$
forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. Num a => a -> a -> a
(+) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
x forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe n
a) (forall a. Num a => a -> a -> a
(+) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
y forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe n
b)
subNumSpec :: (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
subNumSpec :: forall n. (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
subNumSpec (NumSpecInterval Maybe n
x Maybe n
y) (NumSpecInterval Maybe n
a Maybe n
b) =
forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty Maybe n
x Maybe n
y forall a b. (a -> b) -> a -> b
$
forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty Maybe n
a Maybe n
b forall a b. (a -> b) -> a -> b
$
forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval ((-) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
x forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe n
b) ((-) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
y forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe n
a)
multNumSpec :: (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
multNumSpec :: forall n. (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
multNumSpec (NumSpecInterval Maybe n
a Maybe n
b) (NumSpecInterval Maybe n
c Maybe n
d) =
forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty Maybe n
a Maybe n
b forall a b. (a -> b) -> a -> b
$
forall n.
(Ord n, Num n) =>
Maybe n -> Maybe n -> NumSpec n -> NumSpec n
guardEmpty Maybe n
c Maybe n
d forall a b. (a -> b) -> a -> b
$
forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall x. T x -> Maybe x
unT (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [T n]
s)) (forall x. T x -> Maybe x
unT (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [T n]
s))
where
s :: [T n]
s = [forall x. Num x => T x -> T x -> T x
multT (forall x. Maybe x -> T x
neg Maybe n
a) (forall x. Maybe x -> T x
neg Maybe n
c), forall x. Num x => T x -> T x -> T x
multT (forall x. Maybe x -> T x
neg Maybe n
a) (forall x. Maybe x -> T x
pos Maybe n
d), forall x. Num x => T x -> T x -> T x
multT (forall x. Maybe x -> T x
pos Maybe n
b) (forall x. Maybe x -> T x
neg Maybe n
c), forall x. Num x => T x -> T x -> T x
multT (forall x. Maybe x -> T x
pos Maybe n
b) (forall x. Maybe x -> T x
pos Maybe n
d)]
negNumSpec :: Num n => NumSpec n -> NumSpec n
negNumSpec :: forall n. Num n => NumSpec n -> NumSpec n
negNumSpec (NumSpecInterval Maybe n
lo Maybe n
hi) = forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
hi) (forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
lo)
instance Num (NumSpec Integer) where
+ :: NumSpec Integer -> NumSpec Integer -> NumSpec Integer
(+) = forall n. (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
addNumSpec
(-) = forall n. (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
subNumSpec
* :: NumSpec Integer -> NumSpec Integer -> NumSpec Integer
(*) = forall n. (Ord n, Num n) => NumSpec n -> NumSpec n -> NumSpec n
multNumSpec
negate :: NumSpec Integer -> NumSpec Integer
negate = forall n. Num n => NumSpec n -> NumSpec n
negNumSpec
fromInteger :: Integer -> NumSpec Integer
fromInteger Integer
n = forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
fromInteger Integer
n)) (forall a. a -> Maybe a
Just (forall a. Num a => Integer -> a
fromInteger Integer
n))
abs :: NumSpec Integer -> NumSpec Integer
abs = forall a. HasCallStack => String -> a
error String
"No abs in the Num (NumSpec Integer) instance"
signum :: NumSpec Integer -> NumSpec Integer
signum = forall a. HasCallStack => String -> a
error String
"No signum in the Num (NumSpec Integer) instance"
data T x = NegInf | Ok x | PosInf
deriving (Int -> T x -> ShowS
forall x. Show x => Int -> T x -> ShowS
forall x. Show x => [T x] -> ShowS
forall x. Show x => T x -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [T x] -> ShowS
$cshowList :: forall x. Show x => [T x] -> ShowS
show :: T x -> String
$cshow :: forall x. Show x => T x -> String
showsPrec :: Int -> T x -> ShowS
$cshowsPrec :: forall x. Show x => Int -> T x -> ShowS
Show)
instance Ord x => Eq (T x) where
T x
x == :: T x -> T x -> Bool
== T x
y = forall a. Ord a => a -> a -> Ordering
compare T x
x T x
y forall a. Eq a => a -> a -> Bool
== Ordering
EQ
instance Ord x => Ord (T x) where
compare :: T x -> T x -> Ordering
compare T x
NegInf T x
NegInf = Ordering
EQ
compare T x
NegInf T x
_ = Ordering
LT
compare (Ok x
_) T x
NegInf = Ordering
GT
compare (Ok x
x) (Ok x
y) = forall a. Ord a => a -> a -> Ordering
compare x
x x
y
compare (Ok x
_) T x
PosInf = Ordering
LT
compare T x
PosInf T x
PosInf = Ordering
EQ
compare T x
PosInf T x
_ = Ordering
GT
unT :: T x -> Maybe x
unT :: forall x. T x -> Maybe x
unT (Ok x
x) = forall a. a -> Maybe a
Just x
x
unT T x
_ = forall a. Maybe a
Nothing
neg :: Maybe x -> T x
neg :: forall x. Maybe x -> T x
neg Maybe x
Nothing = forall x. T x
NegInf
neg (Just x
x) = forall x. x -> T x
Ok x
x
pos :: Maybe x -> T x
pos :: forall x. Maybe x -> T x
pos Maybe x
Nothing = forall x. T x
PosInf
pos (Just x
x) = forall x. x -> T x
Ok x
x
multT :: Num x => T x -> T x -> T x
multT :: forall x. Num x => T x -> T x -> T x
multT T x
NegInf T x
NegInf = forall x. T x
PosInf
multT T x
NegInf T x
PosInf = forall x. T x
NegInf
multT T x
NegInf (Ok x
_) = forall x. T x
NegInf
multT (Ok x
_) T x
NegInf = forall x. T x
NegInf
multT (Ok x
x) (Ok x
y) = forall x. x -> T x
Ok (x
x forall a. Num a => a -> a -> a
* x
y)
multT (Ok x
_) T x
PosInf = forall x. T x
PosInf
multT T x
PosInf T x
PosInf = forall x. T x
PosInf
multT T x
PosInf T x
NegInf = forall x. T x
NegInf
multT T x
PosInf (Ok x
_) = forall x. T x
PosInf
type Number n = (Num n, Enum n, TypeSpec n ~ NumSpec n, Num (NumSpec n), HasSpec n, Ord n)
addSpecInt ::
Number n =>
Specification n -> Specification n -> Specification n
addSpecInt :: forall n.
Number n =>
Specification n -> Specification n -> Specification n
addSpecInt Specification n
x Specification n
y = forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
" + " forall a. Num a => a -> a -> a
(+) forall a. Num a => a -> a -> a
(+) Specification n
x Specification n
y
subSpecInt ::
Number n =>
Specification n -> Specification n -> Specification n
subSpecInt :: forall n.
Number n =>
Specification n -> Specification n -> Specification n
subSpecInt Specification n
x Specification n
y = forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
" - " (-) (-) Specification n
x Specification n
y
multSpecInt ::
Number n =>
Specification n -> Specification n -> Specification n
multSpecInt :: forall n.
Number n =>
Specification n -> Specification n -> Specification n
multSpecInt Specification n
x Specification n
y = forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
" * " forall a. Num a => a -> a -> a
(*) forall a. Num a => a -> a -> a
(*) Specification n
x Specification n
y
operateSpec ::
Number n =>
String ->
(n -> n -> n) ->
(TypeSpec n -> TypeSpec n -> TypeSpec n) ->
Specification n ->
Specification n ->
Specification n
operateSpec :: forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
operator n -> n -> n
f TypeSpec n -> TypeSpec n -> TypeSpec n
ft (ExplainSpec [String]
es Specification n
x) Specification n
y = forall a. [String] -> Specification a -> Specification a
explainSpecOpt [String]
es forall a b. (a -> b) -> a -> b
$ forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
operator n -> n -> n
f TypeSpec n -> TypeSpec n -> TypeSpec n
ft Specification n
x Specification n
y
operateSpec String
operator n -> n -> n
f TypeSpec n -> TypeSpec n -> TypeSpec n
ft Specification n
x (ExplainSpec [String]
es Specification n
y) = forall a. [String] -> Specification a -> Specification a
explainSpecOpt [String]
es forall a b. (a -> b) -> a -> b
$ forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
operator n -> n -> n
f TypeSpec n -> TypeSpec n -> TypeSpec n
ft Specification n
x Specification n
y
operateSpec String
operator n -> n -> n
f TypeSpec n -> TypeSpec n -> TypeSpec n
ft Specification n
x Specification n
y = case (Specification n
x, Specification n
y) of
(ErrorSpec NonEmpty String
xs, ErrorSpec NonEmpty String
ys) -> forall a. NonEmpty String -> Specification a
ErrorSpec (NonEmpty String
xs forall a. Semigroup a => a -> a -> a
<> NonEmpty String
ys)
(ErrorSpec NonEmpty String
xs, Specification n
_) -> forall a. NonEmpty String -> Specification a
ErrorSpec NonEmpty String
xs
(Specification n
_, ErrorSpec NonEmpty String
ys) -> forall a. NonEmpty String -> Specification a
ErrorSpec NonEmpty String
ys
(Specification n
TrueSpec, Specification n
_) -> forall a. Specification a
TrueSpec
(Specification n
_, Specification n
TrueSpec) -> forall a. Specification a
TrueSpec
(Specification n
_, SuspendedSpec Var n
_ Pred
_) -> forall a. Specification a
TrueSpec
(SuspendedSpec Var n
_ Pred
_, Specification n
_) -> forall a. Specification a
TrueSpec
(TypeSpec TypeSpec n
a [n]
bad1, TypeSpec TypeSpec n
b [n]
bad2) -> forall a. HasSpec a => TypeSpec a -> [a] -> Specification a
TypeSpec (TypeSpec n -> TypeSpec n -> TypeSpec n
ft TypeSpec n
a TypeSpec n
b) [n -> n -> n
f n
b1 n
b2 | n
b1 <- [n]
bad1, n
b2 <- [n]
bad2]
(MemberSpec NonEmpty n
xs, MemberSpec NonEmpty n
ys) ->
forall a. Ord a => String -> [a] -> Specification a
nubOrdMemberSpec
(forall a. Show a => a -> String
show Specification n
x forall a. [a] -> [a] -> [a]
++ String
operator forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Specification n
y)
[n -> n -> n
f n
x1 n
y1 | n
x1 <- forall a. NonEmpty a -> [a]
NE.toList NonEmpty n
xs, n
y1 <- forall a. NonEmpty a -> [a]
NE.toList NonEmpty n
ys]
(MemberSpec NonEmpty n
ys, TypeSpec (NumSpecInterval (Just n
i) (Just n
j)) [n]
bad) ->
let xs :: [n]
xs = forall a. NonEmpty a -> [a]
NE.toList NonEmpty n
ys
in forall a. Ord a => String -> [a] -> Specification a
nubOrdMemberSpec
(forall a. Show a => a -> String
show Specification n
x forall a. [a] -> [a] -> [a]
++ String
operator forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Specification n
y)
[n -> n -> n
f n
x1 n
y1 | n
x1 <- [n]
xs, n
y1 <- [n
i .. n
j], Bool -> Bool
not (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem n
y1 [n]
bad)]
(MemberSpec NonEmpty n
ys, TypeSpec (NumSpecInterval Maybe n
lo Maybe n
hi) [n]
bads) ->
let xs :: [n]
xs = forall a. NonEmpty a -> [a]
NE.toList NonEmpty n
ys
in forall a. HasSpec a => TypeSpec a -> [a] -> Specification a
typeSpecOpt
(forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (n -> n -> n
f (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [n]
xs) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
lo) (n -> n -> n
f (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [n]
xs) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe n
hi))
[n -> n -> n
f n
x1 n
b | n
x1 <- [n]
xs, n
b <- [n]
bads]
(Specification n
sleft, Specification n
sright) -> forall n.
Number n =>
String
-> (n -> n -> n)
-> (TypeSpec n -> TypeSpec n -> TypeSpec n)
-> Specification n
-> Specification n
-> Specification n
operateSpec String
operator (\n
a n
b -> n -> n -> n
f n
b n
a) (\TypeSpec n
u TypeSpec n
v -> TypeSpec n -> TypeSpec n -> TypeSpec n
ft TypeSpec n
v TypeSpec n
u) Specification n
sright Specification n
sleft
instance Number Integer => Num (Specification Integer) where
+ :: Specification Integer
-> Specification Integer -> Specification Integer
(+) = forall n.
Number n =>
Specification n -> Specification n -> Specification n
addSpecInt
(-) = forall n.
Number n =>
Specification n -> Specification n -> Specification n
subSpecInt
* :: Specification Integer
-> Specification Integer -> Specification Integer
(*) = forall n.
Number n =>
Specification n -> Specification n -> Specification n
multSpecInt
fromInteger :: Integer -> Specification Integer
fromInteger Integer
n = forall a. HasSpec a => TypeSpec a -> [a] -> Specification a
TypeSpec (forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. a -> Maybe a
Just Integer
n) (forall a. a -> Maybe a
Just Integer
n)) []
abs :: Specification Integer -> Specification Integer
abs Specification Integer
_ = forall a. Specification a
TrueSpec
signum :: Specification Integer -> Specification Integer
signum Specification Integer
_ = forall a. Specification a
TrueSpec
cardinality ::
forall a. (Number Integer, HasSpec a) => Specification a -> Specification Integer
cardinality :: forall a.
(Number Integer, HasSpec a) =>
Specification a -> Specification Integer
cardinality (ExplainSpec [String]
es Specification a
s) = forall a. [String] -> Specification a -> Specification a
explainSpecOpt [String]
es (forall a.
(Number Integer, HasSpec a) =>
Specification a -> Specification Integer
cardinality Specification a
s)
cardinality Specification a
TrueSpec = forall a. HasSpec a => Specification Integer
cardinalTrueSpec @a
cardinality (MemberSpec NonEmpty a
es) = forall a. a -> Specification a
equalSpec (forall a. Integral a => a -> Integer
toInteger forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall a. Eq a => [a] -> [a]
nub (forall a. NonEmpty a -> [a]
NE.toList NonEmpty a
es)))
cardinality ErrorSpec {} = forall a. a -> Specification a
equalSpec Integer
0
cardinality (TypeSpec TypeSpec a
s [a]
cant) =
forall n.
Number n =>
Specification n -> Specification n -> Specification n
subSpecInt
(forall a. HasSpec a => TypeSpec a -> Specification Integer
cardinalTypeSpec @a TypeSpec a
s)
(forall a. a -> Specification a
equalSpec (forall a. Integral a => a -> Integer
toInteger forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter (\a
c -> forall a. (HasSpec a, HasCallStack) => a -> TypeSpec a -> Bool
conformsTo @a a
c TypeSpec a
s) [a]
cant)))
cardinality SuspendedSpec {} = forall a. HasSpec a => Specification Integer
cardinalTrueSpec @a
cardinalNumSpec ::
forall n. (Integral n, MaybeBounded n) => NumSpec n -> Specification Integer
cardinalNumSpec :: forall n.
(Integral n, MaybeBounded n) =>
NumSpec n -> Specification Integer
cardinalNumSpec (NumSpecInterval (Just n
lo) (Just n
hi)) =
if n
hi forall a. Ord a => a -> a -> Bool
>= n
lo then forall a. NonEmpty a -> Specification a
MemberSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Integral a => a -> Integer
toInteger n
hi forall a. Num a => a -> a -> a
- forall a. Integral a => a -> Integer
toInteger n
lo forall a. Num a => a -> a -> a
+ Integer
1)) else forall a. NonEmpty a -> Specification a
MemberSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure Integer
0)
cardinalNumSpec (NumSpecInterval Maybe n
Nothing (Just n
hi)) =
case forall a. MaybeBounded a => Maybe a
lowerBound @n of
Just n
lo -> forall a. NonEmpty a -> Specification a
MemberSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Integral a => a -> Integer
toInteger n
hi forall a. Num a => a -> a -> a
- forall a. Integral a => a -> Integer
toInteger n
lo))
Maybe n
Nothing -> forall a. Specification a
TrueSpec
cardinalNumSpec (NumSpecInterval (Just n
lo) Maybe n
Nothing) =
case forall a. MaybeBounded a => Maybe a
upperBound @n of
Just n
hi -> forall a. NonEmpty a -> Specification a
MemberSpec (forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Integral a => a -> Integer
toInteger n
hi forall a. Num a => a -> a -> a
- forall a. Integral a => a -> Integer
toInteger n
lo))
Maybe n
Nothing -> forall a. Specification a
TrueSpec
cardinalNumSpec (NumSpecInterval Maybe n
Nothing Maybe n
Nothing) = forall a. Specification a
TrueSpec
class (Num a, HasSpec a) => NumLike a where
subtractSpec :: a -> TypeSpec a -> Specification a
default subtractSpec ::
( TypeSpec a ~ TypeSpec (SimpleRep a)
, HasSimpleRep a
, NumLike (SimpleRep a)
) =>
a ->
TypeSpec a ->
Specification a
subtractSpec a
a TypeSpec a
ts = forall a.
(HasSpec a, HasSimpleRep a, TypeSpec a ~ TypeSpec (SimpleRep a)) =>
Specification (SimpleRep a) -> Specification a
fromSimpleRepSpec forall a b. (a -> b) -> a -> b
$ forall a. NumLike a => a -> TypeSpec a -> Specification a
subtractSpec (forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep a
a) TypeSpec a
ts
negateSpec :: TypeSpec a -> Specification a
default negateSpec ::
( TypeSpec a ~ TypeSpec (SimpleRep a)
, HasSimpleRep a
, NumLike (SimpleRep a)
) =>
TypeSpec a ->
Specification a
negateSpec = forall a.
(HasSpec a, HasSimpleRep a, TypeSpec a ~ TypeSpec (SimpleRep a)) =>
Specification (SimpleRep a) -> Specification a
fromSimpleRepSpec forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. NumLike a => TypeSpec a -> Specification a
negateSpec @(SimpleRep a)
safeSubtract :: a -> a -> Maybe a
default safeSubtract ::
(HasSimpleRep a, NumLike (SimpleRep a)) =>
a ->
a ->
Maybe a
safeSubtract a
a a
b = forall a. HasSimpleRep a => SimpleRep a -> a
fromSimpleRep forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. NumLike a => a -> a -> Maybe a
safeSubtract @(SimpleRep a) (forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep a
a) (forall a. HasSimpleRep a => a -> SimpleRep a
toSimpleRep a
b)
data IntW (s :: Symbol) (as :: [Type]) b where
AddW :: NumLike a => IntW "addFn" '[a, a] a
NegateW :: NumLike a => IntW "negateFn" '[a] a
deriving instance Eq (IntW s dom rng)
instance Show (IntW s d r) where
show :: IntW s d r -> String
show IntW s d r
AddW = String
"addFn"
show IntW s d r
NegateW = String
"negateFn"
instance Semantics IntW where
semantics :: forall (s :: Symbol) (d :: [*]) r. IntW s d r -> FunTy d r
semantics IntW s d r
AddW = forall a. Num a => a -> a -> a
(+)
semantics IntW s d r
NegateW = forall a. Num a => a -> a
negate
instance Syntax IntW
type Numeric a = (HasSpec a, Ord a, Num a, TypeSpec a ~ NumSpec a, MaybeBounded a)
instance {-# OVERLAPPABLE #-} Numeric a => NumLike a where
subtractSpec :: a -> TypeSpec a -> Specification a
subtractSpec a
a ts :: TypeSpec a
ts@(NumSpecInterval Maybe a
ml Maybe a
mu)
| Just a
u <- Maybe a
mu
, a
a forall a. Ord a => a -> a -> Bool
> a
0
, Maybe a
Nothing <- forall a. NumLike a => a -> a -> Maybe a
safeSubtract a
a a
u =
forall a. NonEmpty String -> Specification a
ErrorSpec forall a b. (a -> b) -> a -> b
$
forall a. [a] -> NonEmpty a
NE.fromList
[ String
"Underflow in subtractSpec (" forall a. [a] -> [a] -> [a]
++ forall {k} (t :: k). Typeable t => String
showType @a forall a. [a] -> [a] -> [a]
++ String
"):"
, String
" a = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
a
, String
" ts = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show TypeSpec a
ts
]
| Just a
l <- Maybe a
ml
, a
a forall a. Ord a => a -> a -> Bool
< a
0
, Maybe a
Nothing <- forall a. NumLike a => a -> a -> Maybe a
safeSubtract a
a a
l =
forall a. NonEmpty String -> Specification a
ErrorSpec forall a b. (a -> b) -> a -> b
$
forall a. [a] -> NonEmpty a
NE.fromList
[ String
"Overflow in subtractSpec (" forall a. [a] -> [a] -> [a]
++ forall {k} (t :: k). Typeable t => String
showType @a forall a. [a] -> [a] -> [a]
++ String
"):"
, String
" a = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
a
, String
" ts = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show TypeSpec a
ts
]
| Bool
otherwise = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (a -> a -> a
safeSub a
a forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
ml) (a -> a -> a
safeSub a
a forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
mu)
where
safeSub :: a -> a -> a
safeSub :: a -> a -> a
safeSub a
a1 a
x
| Just a
r <- forall a. NumLike a => a -> a -> Maybe a
safeSubtract a
a1 a
x = a
r
| a
a1 forall a. Ord a => a -> a -> Bool
< a
0 = forall a. HasCallStack => Maybe a -> a
fromJust forall a. MaybeBounded a => Maybe a
upperBound
| Bool
otherwise = forall a. HasCallStack => Maybe a -> a
fromJust forall a. MaybeBounded a => Maybe a
lowerBound
negateSpec :: TypeSpec a -> Specification a
negateSpec (NumSpecInterval Maybe a
ml Maybe a
mu) = forall a. HasSpec a => TypeSpec a -> Specification a
typeSpec forall a b. (a -> b) -> a -> b
$ forall n. Maybe n -> Maybe n -> NumSpec n
NumSpecInterval (forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
mu) (forall a. Num a => a -> a
negate forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
ml)
safeSubtract :: a -> a -> Maybe a
safeSubtract a
a a
x
| a
a forall a. Ord a => a -> a -> Bool
> a
0
, Just a
lb <- forall a. MaybeBounded a => Maybe a
lowerBound
, a
lb forall a. Num a => a -> a -> a
+ a
a forall a. Ord a => a -> a -> Bool
> a
x =
forall a. Maybe a
Nothing
| a
a forall a. Ord a => a -> a -> Bool
< a
0
, Just a
ub <- forall a. MaybeBounded a => Maybe a
upperBound
, a
ub forall a. Num a => a -> a -> a
+ a
a forall a. Ord a => a -> a -> Bool
< a
x =
forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ a
x forall a. Num a => a -> a -> a
- a
a
instance NumLike a => Num (Term a) where
+ :: Term a -> Term a -> Term a
(+) = forall a. NumLike a => Term a -> Term a -> Term a
addFn
negate :: Term a -> Term a
negate = forall a. NumLike a => Term a -> Term a
negateFn
fromInteger :: Integer -> Term a
fromInteger = forall a. Literal a => a -> Term a
Lit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => Integer -> a
fromInteger
* :: Term a -> Term a -> Term a
(*) = forall a. HasCallStack => String -> a
error String
"(*) not implemented for Term Fn Int"
abs :: Term a -> Term a
abs = forall a. HasCallStack => String -> a
error String
"abs not implemented for Term Fn Int"
signum :: Term a -> Term a
signum = forall a. HasCallStack => String -> a
error String
"signum not implemented for Term Fn Int"
instance NumLike a => Logic "addFn" IntW '[a, a] a where
propagate :: forall hole.
Context "addFn" IntW '[a, a] a hole
-> Specification a -> Specification hole
propagate Context "addFn" IntW '[a, a] a hole
ctxt (ExplainSpec [] Specification a
s) = forall (s :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
rng hole.
Logic s t dom rng =>
Context s t dom rng hole -> Specification rng -> Specification hole
propagate Context "addFn" IntW '[a, a] a hole
ctxt Specification a
s
propagate Context "addFn" IntW '[a, a] a hole
ctxt (ExplainSpec [String]
es Specification a
s) = forall a. [String] -> Specification a -> Specification a
ExplainSpec [String]
es forall a b. (a -> b) -> a -> b
$ forall (s :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
rng hole.
Logic s t dom rng =>
Context s t dom rng hole -> Specification rng -> Specification hole
propagate Context "addFn" IntW '[a, a] a hole
ctxt Specification a
s
propagate Context "addFn" IntW '[a, a] a hole
_ Specification a
TrueSpec = forall a. Specification a
TrueSpec
propagate Context "addFn" IntW '[a, a] a hole
_ (ErrorSpec NonEmpty String
msgs) = forall a. NonEmpty String -> Specification a
ErrorSpec NonEmpty String
msgs
propagate (Context IntW "addFn" '[a, a] a
AddW (Ctx hole y
HOLE :<> a
x :<| CList 'Post as1 Any Any
End)) (SuspendedSpec Var a
v Pred
ps) =
forall a p.
(IsPred p, HasSpec a) =>
(Term a -> p) -> Specification a
constrained forall a b. (a -> b) -> a -> b
$ \Term hole
v' -> forall a. Term a -> Binder a -> Pred
Let (forall (sym :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
a.
AppRequires sym t dom a =>
t sym dom a -> List Term dom -> Term a
App forall a. NumLike a => IntW "addFn" '[a, a] a
AddW (Term hole
v' forall {k} (f :: k -> *) (a :: k) (as1 :: [k]).
f a -> List f as1 -> List f (a : as1)
:> forall a. Literal a => a -> Term a
Lit a
x forall {k} (f :: k -> *) (a :: k) (as1 :: [k]).
f a -> List f as1 -> List f (a : as1)
:> forall {k} (f :: k -> *). List f '[]
Nil)) (Var a
v forall a. HasSpec a => Var a -> Pred -> Binder a
:-> Pred
ps)
propagate (Context IntW "addFn" '[a, a] a
AddW (a
x :|> Ctx hole y
HOLE :<> CList 'Post as1 Any Any
forall i j. CList 'Post as1 i j
End)) (SuspendedSpec Var a
v Pred
ps) =
forall a p.
(IsPred p, HasSpec a) =>
(Term a -> p) -> Specification a
constrained forall a b. (a -> b) -> a -> b
$ \Term hole
v' -> forall a. Term a -> Binder a -> Pred
Let (forall (sym :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
a.
AppRequires sym t dom a =>
t sym dom a -> List Term dom -> Term a
App forall a. NumLike a => IntW "addFn" '[a, a] a
AddW (forall a. Literal a => a -> Term a
Lit a
x forall {k} (f :: k -> *) (a :: k) (as1 :: [k]).
f a -> List f as1 -> List f (a : as1)
:> Term hole
v' forall {k} (f :: k -> *) (a :: k) (as1 :: [k]).
f a -> List f as1 -> List f (a : as1)
:> forall {k} (f :: k -> *). List f '[]
Nil)) (Var a
v forall a. HasSpec a => Var a -> Pred -> Binder a
:-> Pred
ps)
propagate (Context IntW "addFn" '[a, a] a
AddW (a
i :|> Ctx hole y
HOLE :<> CList 'Post as1 Any Any
forall i j. CList 'Post as1 i j
End)) Specification a
spec =
forall (s :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
rng hole.
Logic s t dom rng =>
Context s t dom rng hole -> Specification rng -> Specification hole
propagate (forall (dom :: [*]) rng (t :: Symbol -> [*] -> * -> *)
(s :: Symbol) hole y.
(All HasSpec dom, HasSpec rng) =>
t s dom rng -> CList 'Pre dom hole y -> Context s t dom rng hole
Context forall a. NumLike a => IntW "addFn" '[a, a] a
AddW (forall hole. HasSpec hole => Ctx hole hole
HOLE forall y hole (as1 :: [*]).
HasSpec y =>
Ctx hole y
-> (forall i j. CList 'Post as1 i j) -> CList 'Pre (y : as1) hole y
:<> a
i forall a (as1 :: [*]) hole y.
Literal a =>
a -> CList 'Post as1 hole y -> CList 'Post (a : as1) hole y
:<| forall hole y. CList 'Post '[] hole y
End)) Specification a
spec
propagate (Context IntW "addFn" '[a, a] a
AddW (Ctx hole y
HOLE :<> a
i :<| CList 'Post as1 Any Any
End)) (TypeSpec TypeSpec a
ts [a]
cant) =
forall a. NumLike a => a -> TypeSpec a -> Specification a
subtractSpec a
i TypeSpec a
ts forall a. Semigroup a => a -> a -> a
<> forall a (f :: * -> *).
(HasSpec a, Foldable f) =>
f a -> Specification a
notMemberSpec (forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall a. NumLike a => a -> a -> Maybe a
safeSubtract a
i) [a]
cant)
propagate (Context IntW "addFn" '[a, a] a
AddW (Ctx hole y
HOLE :<> a
i :<| CList 'Post as1 Any Any
End)) (MemberSpec NonEmpty a
es) =
forall a. [a] -> NonEmpty String -> Specification a
memberSpecList
(forall a. Eq a => [a] -> [a]
nub forall a b. (a -> b) -> a -> b
$ forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall a. NumLike a => a -> a -> Maybe a
safeSubtract a
i) (forall a. NonEmpty a -> [a]
NE.toList NonEmpty a
es))
( forall a. [a] -> NonEmpty a
NE.fromList
[ String
"propagateSpecFn on (" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
i forall a. [a] -> [a] -> [a]
++ String
" +. HOLE)"
, String
"The Spec is a MemberSpec = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall a. NonEmpty a -> Specification a
MemberSpec NonEmpty a
es)
, String
"We can't safely subtract " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
i forall a. [a] -> [a] -> [a]
++ String
" from any choice in the MemberSpec."
]
)
propagate Context "addFn" IntW '[a, a] a hole
ctx Specification a
_ =
forall a. NonEmpty String -> Specification a
ErrorSpec forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
"Logic instance for AddW with wrong number of arguments. " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Context "addFn" IntW '[a, a] a hole
ctx)
addFn :: forall a. NumLike a => Term a -> Term a -> Term a
addFn :: forall a. NumLike a => Term a -> Term a -> Term a
addFn = forall (sym :: Symbol) (t :: Symbol -> [*] -> * -> *) (ds :: [*])
r.
AppRequires sym t ds r =>
t sym ds r -> FunTy (MapList Term ds) (Term r)
appTerm forall a. NumLike a => IntW "addFn" '[a, a] a
AddW
instance NumLike a => Logic "negateFn" IntW '[a] a where
propagate :: forall hole.
Context "negateFn" IntW '[a] a hole
-> Specification a -> Specification hole
propagate Context "negateFn" IntW '[a] a hole
ctxt (ExplainSpec [] Specification a
s) = forall (s :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
rng hole.
Logic s t dom rng =>
Context s t dom rng hole -> Specification rng -> Specification hole
propagate Context "negateFn" IntW '[a] a hole
ctxt Specification a
s
propagate Context "negateFn" IntW '[a] a hole
ctxt (ExplainSpec [String]
es Specification a
s) = forall a. [String] -> Specification a -> Specification a
ExplainSpec [String]
es forall a b. (a -> b) -> a -> b
$ forall (s :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
rng hole.
Logic s t dom rng =>
Context s t dom rng hole -> Specification rng -> Specification hole
propagate Context "negateFn" IntW '[a] a hole
ctxt Specification a
s
propagate Context "negateFn" IntW '[a] a hole
_ Specification a
TrueSpec = forall a. Specification a
TrueSpec
propagate Context "negateFn" IntW '[a] a hole
_ (ErrorSpec NonEmpty String
msgs) = forall a. NonEmpty String -> Specification a
ErrorSpec NonEmpty String
msgs
propagate (Context IntW "negateFn" '[a] a
NegateW (Ctx hole y
HOLE :<> CList 'Post as1 Any Any
forall i j. CList 'Post as1 i j
End)) (SuspendedSpec Var a
v Pred
ps) =
forall a p.
(IsPred p, HasSpec a) =>
(Term a -> p) -> Specification a
constrained forall a b. (a -> b) -> a -> b
$ \Term hole
v' -> forall a. Term a -> Binder a -> Pred
Let (forall (sym :: Symbol) (t :: Symbol -> [*] -> * -> *) (dom :: [*])
a.
AppRequires sym t dom a =>
t sym dom a -> List Term dom -> Term a
App forall a. NumLike a => IntW "negateFn" '[a] a
NegateW (Term hole
v' forall {k} (f :: k -> *) (a :: k) (as1 :: [k]).
f a -> List f as1 -> List f (a : as1)
:> forall {k} (f :: k -> *). List f '[]
Nil)) (Var a
v forall a. HasSpec a => Var a -> Pred -> Binder a
:-> Pred
ps)
propagate (Context IntW "negateFn" '[a] a
NegateW (Ctx hole y
HOLE :<> CList 'Post as1 Any Any
forall i j. CList 'Post as1 i j
End)) (TypeSpec TypeSpec a
ts [a]
cant) =
forall a. NumLike a => TypeSpec a -> Specification a
negateSpec @a TypeSpec a
ts forall a. Semigroup a => a -> a -> a
<> forall a (f :: * -> *).
(HasSpec a, Foldable f) =>
f a -> Specification a
notMemberSpec (forall a b. (a -> b) -> [a] -> [b]
map forall a. Num a => a -> a
negate [a]
cant)
propagate (Context IntW "negateFn" '[a] a
NegateW (Ctx hole y
HOLE :<> CList 'Post as1 Any Any
forall i j. CList 'Post as1 i j
End)) (MemberSpec NonEmpty a
es) =
forall a. NonEmpty a -> Specification a
MemberSpec forall a b. (a -> b) -> a -> b
$ forall a. Eq a => NonEmpty a -> NonEmpty a
NE.nub forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Num a => a -> a
negate NonEmpty a
es
propagate Context "negateFn" IntW '[a] a hole
ctx Specification a
_ =
forall a. NonEmpty String -> Specification a
ErrorSpec forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure (String
"Logic instance for NegateW with wrong number of arguments. " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Context "negateFn" IntW '[a] a hole
ctx)
mapTypeSpec :: forall a b.
('[a] ~ '[a], a ~ b, HasSpec a, HasSpec b) =>
IntW "negateFn" '[a] b -> TypeSpec a -> Specification b
mapTypeSpec IntW "negateFn" '[a] b
NegateW (TypeSpec a
ts) = forall a. NumLike a => TypeSpec a -> Specification a
negateSpec TypeSpec a
ts
negateFn :: forall a. NumLike a => Term a -> Term a
negateFn :: forall a. NumLike a => Term a -> Term a
negateFn = forall (sym :: Symbol) (t :: Symbol -> [*] -> * -> *) (ds :: [*])
r.
AppRequires sym t ds r =>
t sym ds r -> FunTy (MapList Term ds) (Term r)
appTerm forall a. NumLike a => IntW "negateFn" '[a] a
NegateW