-- |
-- Module      : Conjure.Conjurable
-- Copyright   : (c) 2021 Rudy Matela
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : Rudy Matela <rudy@matela.com.br>
--
-- This module is part of 'Conjure'.
--
-- This defines the 'Conjurable' typeclass
-- and utilities involving it.
--
-- You are probably better off importing "Conjure".
{-# Language DeriveDataTypeable, StandaloneDeriving #-} -- for GHC < 7.10
module Conjure.Conjurable
  ( Reification1
  , Reification
  , Conjurable (..)
  , conjureType
  , reifyTiers
  , reifyEquality
  , conjureApplication
  , conjureVarApplication
  , conjureHoles
  , conjureIfs
  , conjureTiersFor
  , conjureAreEqual
  , conjureMkEquation
  , A, B, C, D, E, F
  , conjureIsDeconstructor
  )
where

import Test.LeanCheck
import Test.LeanCheck.Utils
import Test.LeanCheck.Error (errorToFalse)
import Conjure.Expr hiding (application)
import Conjure.Constructors
import Test.Speculate.Expr
import Data.Functor ((<$>))
import Control.Applicative ((<*>))

import Data.Int     -- for instances
import Data.Word    -- for instances
import Data.Ratio   -- for instance
import Data.Complex -- for instance


-- | Single reification of some functions over a type as 'Expr's.
--
-- A hole, an if function, an equality function and tiers.
type Reification1  =  (Expr, Expr, Maybe Expr, Maybe [[Expr]])

-- | A reification over a collection of types.
--
-- Represented as a transformation of a list to a list.
type Reification  =  [Reification1] -> [Reification1]


-- | Class of 'Conjurable' types.
-- Functions are 'Conjurable'
-- if all their arguments are 'Conjurable', 'Listable' and 'Show'able.
--
-- For atomic types that are 'Listable',
-- instances are defined as:
--
-- > instance Conjurable Atomic where
-- >   conjureTiers  =  reifyTiers
--
-- For atomic types that are both 'Listable' and 'Eq',
-- instances are defined as:
--
-- > instance Conjurable Atomic where
-- >   conjureTiers     =  reifyTiers
-- >   conjureEquality  =  reifyEquality
--
-- For types with subtypes,
-- instances are defined as:
--
-- > instance Conjurable Composite where
-- >   conjureTiers     =  reifyTiers
-- >   conjureEquality  =  reifyEquality
-- >   conjureSubTypes x  =  conjureType y
-- >                      .  conjureType z
-- >                      .  conjureType w
-- >     where
-- >     (Composite ... y ... z ... w ...)  =  x
--
-- Above @x@, @y@, @z@ and @w@ are just proxies.
-- The @Proxy@ type was avoided for backwards compatibility.
--
-- Please see the source code of "Conjure.Conjurable" for more examples.
--
-- (cf. 'reifyTiers', 'reifyEquality', 'conjureType')
class Typeable a => Conjurable a where
  conjureArgumentHoles :: a -> [Expr]
  conjureArgumentHoles a
_  =  []

  -- | Returns 'Just' the '==' function encoded as an 'Expr' when available
  --   or 'Nothing' otherwise.
  conjureEquality :: a -> Maybe Expr
  conjureEquality a
_  =  Maybe Expr
forall a. Maybe a
Nothing

  -- | Returns 'Just' 'tiers' of values encoded as 'Expr's when possible
  --   or 'Nothing' otherwise.
  conjureTiers :: a -> Maybe [[Expr]]
  conjureTiers a
_  =  Maybe [[Expr]]
forall a. Maybe a
Nothing

  conjureSubTypes :: a -> Reification
  conjureSubTypes a
_  =  Reification
forall a. a -> a
id

  conjureIf :: a -> Expr
  conjureIf   =  a -> Expr
forall a. Typeable a => a -> Expr
ifFor


conjureType :: Conjurable a => a -> Reification
conjureType :: a -> Reification
conjureType a
x [Reification1]
ms  =
  if a -> Expr
forall a. Typeable a => a -> Expr
hole a
x Expr -> [Expr] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Expr
h | (Expr
h,Expr
_,Maybe Expr
_,Maybe [[Expr]]
_) <- [Reification1]
ms]
  then [Reification1]
ms
  else a -> Reification
forall a. Conjurable a => a -> Reification
conjureSubTypes a
x Reification -> Reification
forall a b. (a -> b) -> a -> b
$ a -> Reification1
forall a. Conjurable a => a -> Reification1
conjureReification1 a
x Reification1 -> Reification
forall a. a -> [a] -> [a]
: [Reification1]
ms

-- | like 'conjureType' but without type repetitions
nubConjureType :: Conjurable a => a -> Reification
nubConjureType :: a -> Reification
nubConjureType a
x  =  (Reification1 -> Expr) -> Reification
forall b a. Eq b => (a -> b) -> [a] -> [a]
nubOn (\(Expr
eh,Expr
_,Maybe Expr
_,Maybe [[Expr]]
_) -> Expr
eh) Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
x
-- The use of nubOn above is O(n^2).
-- So long as there is not a huge number of subtypes of a, so we're fine.

conjureReification1 :: Conjurable a => a -> Reification1
conjureReification1 :: a -> Reification1
conjureReification1 a
x  =  (a -> Expr
forall a. Typeable a => a -> Expr
hole a
x, a -> Expr
forall a. Typeable a => a -> Expr
ifFor a
x, a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x, a -> Maybe [[Expr]]
forall a. Conjurable a => a -> Maybe [[Expr]]
conjureTiers a
x)

conjureReification :: Conjurable a => a -> [Reification1]
conjureReification :: a -> [Reification1]
conjureReification a
x  =  a -> Reification
forall a. Conjurable a => a -> Reification
nubConjureType a
x [Bool -> Reification1
forall a. Conjurable a => a -> Reification1
conjureReification1 Bool
bool]
  where
  bool :: Bool
  bool :: Bool
bool  =  [Char] -> Bool
forall a. HasCallStack => [Char] -> a
error [Char]
"conjureReification: evaluated proxy boolean value (definitely a bug)"

-- | Reifies equality to be used in a conjurable type.
--
-- This is to be used
-- in the definition of 'conjureEquality'
-- of 'Conjurable' typeclass instances:
--
-- > instance ... => Conjurable <Type> where
-- >   ...
-- >   conjureEquality  =  reifyEquality
-- >   ...
reifyEquality :: (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality :: a -> Maybe Expr
reifyEquality  =  Expr -> Maybe Expr
forall a. a -> Maybe a
Just (Expr -> Maybe Expr) -> (a -> Expr) -> a -> Maybe Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Expr] -> Expr
forall a. [a] -> a
head ([Expr] -> Expr) -> (a -> [Expr]) -> a -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [Expr]
forall a. (Typeable a, Eq a) => a -> [Expr]
reifyEq

-- | Reifies equality to be used in a conjurable type.
--
-- This is to be used
-- in the definition of 'conjureTiers'
-- of 'Conjurable' typeclass instances:
--
-- > instance ... => Conjurable <Type> where
-- >   ...
-- >   conjureTiers  =  reifyTiers
-- >   ...
reifyTiers :: (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers :: a -> Maybe [[Expr]]
reifyTiers  =  [[Expr]] -> Maybe [[Expr]]
forall a. a -> Maybe a
Just ([[Expr]] -> Maybe [[Expr]])
-> (a -> [[Expr]]) -> a -> Maybe [[Expr]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> [[Expr]]
mkExprTiers

mkExprTiers :: (Listable a, Show a, Typeable a) => a -> [[Expr]]
mkExprTiers :: a -> [[Expr]]
mkExprTiers a
a  =  (a -> Expr) -> [[a]] -> [[Expr]]
forall a b. (a -> b) -> [[a]] -> [[b]]
mapT a -> Expr
forall a. (Typeable a, Show a) => a -> Expr
val ([[a]]
forall a. Listable a => [[a]]
tiers [[a]] -> [[a]] -> [[a]]
forall a. a -> a -> a
-: [[a
a]])

conjureHoles :: Conjurable f => f -> [Expr]
conjureHoles :: f -> [Expr]
conjureHoles f
f  =  [Expr
eh | (Expr
eh,Expr
_,Maybe Expr
_,Just [[Expr]]
_) <- f -> [Reification1]
forall a. Conjurable a => a -> [Reification1]
conjureReification f
f]

conjureIfs :: Conjurable f => f -> [Expr]
conjureIfs :: f -> [Expr]
conjureIfs f
f  =  [Expr
eef | (Expr
_,Expr
eef,Maybe Expr
_,Just [[Expr]]
_) <- f -> Reification
forall a. Conjurable a => a -> Reification
nubConjureType f
f []]
-- this does not include if for bools automatically
-- differently from conjureHoles, conjureMkEquation and conjureTiersFor

conjureMkEquation :: Conjurable f => f -> Expr -> Expr -> Expr
conjureMkEquation :: f -> Expr -> Expr -> Expr
conjureMkEquation f
f  =  [Expr] -> Expr -> Expr -> Expr
mkEquation [Expr
eq | (Expr
_,Expr
_,Just Expr
eq,Maybe [[Expr]]
_) <- f -> [Reification1]
forall a. Conjurable a => a -> [Reification1]
conjureReification f
f]

conjureAreEqual :: Conjurable f => f -> Int -> Expr -> Expr -> Bool
conjureAreEqual :: f -> Int -> Expr -> Expr -> Bool
conjureAreEqual f
f Int
maxTests  =  Expr -> Expr -> Bool
(===)
  where
  -==- :: Expr -> Expr -> Expr
(-==-)  =  f -> Expr -> Expr -> Expr
forall f. Conjurable f => f -> Expr -> Expr -> Expr
conjureMkEquation f
f
  Expr
e1 === :: Expr -> Expr -> Bool
=== Expr
e2  =  Expr -> Bool
isTrue (Expr -> Bool) -> Expr -> Bool
forall a b. (a -> b) -> a -> b
$ Expr
e1 Expr -> Expr -> Expr
-==- Expr
e2
  isTrue :: Expr -> Bool
isTrue  =  (Expr -> Bool) -> [Expr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool -> Bool
errorToFalse (Bool -> Bool) -> (Expr -> Bool) -> Expr -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Expr -> Bool
forall a. Typeable a => a -> Expr -> a
eval Bool
False) ([Expr] -> Bool) -> (Expr -> [Expr]) -> Expr -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> [Expr]
gs
  gs :: Expr -> [Expr]
gs  =  Int -> [Expr] -> [Expr]
forall a. Int -> [a] -> [a]
take Int
maxTests ([Expr] -> [Expr]) -> (Expr -> [Expr]) -> Expr -> [Expr]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Expr -> [[Expr]]) -> Expr -> [Expr]
grounds (f -> Expr -> [[Expr]]
forall f. Conjurable f => f -> Expr -> [[Expr]]
conjureTiersFor f
f)

conjureTiersFor :: Conjurable f => f -> Expr -> [[Expr]]
conjureTiersFor :: f -> Expr -> [[Expr]]
conjureTiersFor f
f Expr
e  =  [[[Expr]]] -> [[Expr]]
tf [[[Expr]]]
allTiers
  where
  allTiers :: [ [[Expr]] ]
  allTiers :: [[[Expr]]]
allTiers  =  [[[Expr]]
etiers | (Expr
_,Expr
_,Maybe Expr
_,Just [[Expr]]
etiers) <- f -> [Reification1]
forall a. Conjurable a => a -> [Reification1]
conjureReification f
f]
  tf :: [[[Expr]]] -> [[Expr]]
tf []  =  [[Expr
e]] -- no tiers found, keep variable
  tf ([[Expr]]
etiers:[[[Expr]]]
etc)  =  case [[Expr]]
etiers of
                      ((Expr
e':[Expr]
_):[[Expr]]
_) | Expr -> TypeRep
typ Expr
e' TypeRep -> TypeRep -> Bool
forall a. Eq a => a -> a -> Bool
== Expr -> TypeRep
typ Expr
e -> [[Expr]]
etiers
                      [[Expr]]
_                            -> [[[Expr]]] -> [[Expr]]
tf [[[Expr]]]
etc

conjureIsDeconstructor :: Conjurable f => f -> Int -> Expr -> Expr -> Expr -> Bool
conjureIsDeconstructor :: f -> Int -> Expr -> Expr -> Expr -> Bool
conjureIsDeconstructor f
f Int
maxTests  =  [Expr] -> Expr -> Expr -> Bool
isDeconstructionE
                                   ([Expr] -> Expr -> Expr -> Bool)
-> (Expr -> [Expr]) -> Expr -> Expr -> Expr -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  Int -> [Expr] -> [Expr]
forall a. Int -> [a] -> [a]
take Int
maxTests
                                   ([Expr] -> [Expr]) -> (Expr -> [Expr]) -> Expr -> [Expr]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  (Expr -> [[Expr]]) -> Expr -> [Expr]
grounds (f -> Expr -> [[Expr]]
forall f. Conjurable f => f -> Expr -> [[Expr]]
conjureTiersFor f
f)

instance Conjurable () where
  conjureEquality :: () -> Maybe Expr
conjureEquality  =  () -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: () -> Maybe [[Expr]]
conjureTiers     =  () -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Bool where
  conjureEquality :: Bool -> Maybe Expr
conjureEquality  =  Bool -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Bool -> Maybe [[Expr]]
conjureTiers     =  Bool -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Int where
  conjureEquality :: Int -> Maybe Expr
conjureEquality  =  Int -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Int -> Maybe [[Expr]]
conjureTiers     =  Int -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Integer where
  conjureEquality :: Integer -> Maybe Expr
conjureEquality  =  Integer -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Integer -> Maybe [[Expr]]
conjureTiers     =  Integer -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Char where
  conjureEquality :: Char -> Maybe Expr
conjureEquality  =  Char -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Char -> Maybe [[Expr]]
conjureTiers     =  Char -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

-- bind equality to the given argument type
(==:) :: (a -> a -> Bool) -> a -> (a -> a -> Bool)
==: :: (a -> a -> Bool) -> a -> a -> a -> Bool
(==:)  =  (a -> a -> Bool) -> a -> a -> a -> Bool
forall a b. a -> b -> a
const

instance (Conjurable a, Listable a, Show a) => Conjurable [a] where
  conjureSubTypes :: [a] -> Reification
conjureSubTypes [a]
xs  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType ([a] -> a
forall a. [a] -> a
head [a]
xs)
  conjureTiers :: [a] -> Maybe [[Expr]]
conjureTiers     =  [a] -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureEquality :: [a] -> Maybe Expr
conjureEquality [a]
xs  =  Expr -> Expr
from (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
    where
    x :: a
x  =  [a] -> a
forall a. [a] -> a
head [a]
xs
    from :: Expr -> Expr
from Expr
e  =  [Char] -> ([a] -> [a] -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" [a] -> [a] -> Bool
(==)
      where
      .==. :: a -> a -> Bool
(.==.)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      []     == :: [a] -> [a] -> Bool
== []     = Bool
True
      (a
x:[a]
xs) == []     = Bool
False
      []     == (a
y:[a]
ys) = Bool
False
      (a
x:[a]
xs) == (a
y:[a]
ys) = a
x a -> a -> Bool
.==. a
y Bool -> Bool -> Bool
&& [a]
xs [a] -> [a] -> Bool
== [a]
ys

instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         ) => Conjurable (a,b) where
  conjureTiers :: (a, b) -> Maybe [[Expr]]
conjureTiers     =  (a, b) -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: (a, b) -> Reification
conjureSubTypes (a, b)
xy  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType ((a, b) -> a
forall a b. (a, b) -> a
fst (a, b)
xy)
                      Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  b -> Reification
forall a. Conjurable a => a -> Reification
conjureType ((a, b) -> b
forall a b. (a, b) -> b
snd (a, b)
xy)
  conjureEquality :: (a, b) -> Maybe Expr
conjureEquality (a, b)
xy  =  Expr -> Expr -> Expr
from (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
y
    where
    (a
x,b
y)  =  (a, b)
xy
    from :: Expr -> Expr -> Expr
from Expr
e1 Expr
e2  =  [Char] -> ((a, b) -> (a, b) -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" (a, b) -> (a, b) -> Bool
(==)
      where
      ==. :: a -> a -> Bool
(==.)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e1 (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      .== :: b -> b -> Bool
(.==)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e2 (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
y
      (a
x1,b
y1) == :: (a, b) -> (a, b) -> Bool
== (a
x2,b
y2)  =  a
x1 a -> a -> Bool
==. a
x2 Bool -> Bool -> Bool
&& b
y1 b -> b -> Bool
.== b
y2


instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         , Conjurable c, Listable c, Show c
         ) => Conjurable (a,b,c) where
  conjureTiers :: (a, b, c) -> Maybe [[Expr]]
conjureTiers     =  (a, b, c) -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: (a, b, c) -> Reification
conjureSubTypes (a, b, c)
xyz =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
x
                      Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  b -> Reification
forall a. Conjurable a => a -> Reification
conjureType b
y
                      Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  c -> Reification
forall a. Conjurable a => a -> Reification
conjureType c
z
                      where (a
x,b
y,c
z) = (a, b, c)
xyz
  conjureEquality :: (a, b, c) -> Maybe Expr
conjureEquality (a, b, c)
xyz  =  Expr -> Expr -> Expr -> Expr
from
                      (Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
                      Maybe (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
y
                      Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> c -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality c
z
    where
    (a
x,b
y,c
z)  =  (a, b, c)
xyz
    from :: Expr -> Expr -> Expr -> Expr
from Expr
e1 Expr
e2 Expr
e3  =  [Char] -> ((a, b, c) -> (a, b, c) -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" (a, b, c) -> (a, b, c) -> Bool
(==)
      where
      ==.. :: a -> a -> Bool
(==..)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e1 (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      .==. :: b -> b -> Bool
(.==.)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e2 (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
y
      ..== :: c -> c -> Bool
(..==)  =  Expr -> c -> c -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e3 (c -> c -> Bool) -> c -> c -> c -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: c
z
      (a
x1,b
y1,c
z1) == :: (a, b, c) -> (a, b, c) -> Bool
== (a
x2,b
y2,c
z2)  =  a
x1 a -> a -> Bool
==.. a
x2
                                Bool -> Bool -> Bool
&& b
y1 b -> b -> Bool
.==. b
y2
                                Bool -> Bool -> Bool
&& c
z1 c -> c -> Bool
..== c
z2

instance (Conjurable a, Listable a, Show a) => Conjurable (Maybe a) where
  conjureTiers :: Maybe a -> Maybe [[Expr]]
conjureTiers     =  Maybe a -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: Maybe a -> Reification
conjureSubTypes Maybe a
mx  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType (Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe a
mx)
  conjureEquality :: Maybe a -> Maybe Expr
conjureEquality Maybe a
mx  =  Expr -> Expr
from (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
    where
    x :: a
x  =  Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust Maybe a
mx
    from :: Expr -> Expr
from Expr
e  =  [Char] -> (Maybe a -> Maybe a -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" Maybe a -> Maybe a -> Bool
(==)
      where
      .==. :: a -> a -> Bool
(.==.)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      Maybe a
Nothing  == :: Maybe a -> Maybe a -> Bool
== Maybe a
Nothing   =  Bool
True
      Maybe a
Nothing  == (Just a
_)  =  Bool
False
      (Just a
_) == Maybe a
Nothing   =  Bool
False
      (Just a
x) == (Just a
y)  =  a
x a -> a -> Bool
.==. a
y


instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         ) => Conjurable (Either a b) where
  conjureTiers :: Either a b -> Maybe [[Expr]]
conjureTiers     =  Either a b -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: Either a b -> Reification
conjureSubTypes Either a b
elr  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
l Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Reification
forall a. Conjurable a => a -> Reification
conjureType b
r
    where
    Left a
l   =  Either a b
elr
    Right b
r  =  Either a b
elr
  conjureEquality :: Either a b -> Maybe Expr
conjureEquality Either a b
elr  =  Expr -> Expr -> Expr
from (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
l Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
r
    where
    Left a
l   =  Either a b
elr
    Right b
r  =  Either a b
elr
    from :: Expr -> Expr -> Expr
from Expr
el Expr
er  =  [Char] -> (Either a b -> Either a b -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" Either a b -> Either a b -> Bool
(==)
      where
      ==. :: a -> a -> Bool
(==.)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
el (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
l
      .== :: b -> b -> Bool
(.==)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
er (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
r
      (Left a
x)  == :: Either a b -> Either a b -> Bool
== (Left a
y)   =  a
x a -> a -> Bool
==. a
y
      (Left a
_)  == (Right b
_)  =  Bool
False
      (Right b
_) == (Left a
_)   =  Bool
False
      (Right b
x) == (Right b
y)  =  b
x b -> b -> Bool
.== b
y

instance (Conjurable a, Conjurable b) => Conjurable (a -> b) where
  conjureArgumentHoles :: (a -> b) -> [Expr]
conjureArgumentHoles a -> b
f  =  a -> Expr
forall a. Typeable a => a -> Expr
hole ((a -> b) -> a
forall a b. (a -> b) -> a
argTy a -> b
f) Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: b -> [Expr]
forall a. Conjurable a => a -> [Expr]
conjureArgumentHoles (a -> b
f a
forall a. HasCallStack => a
undefined)
  conjureSubTypes :: (a -> b) -> Reification
conjureSubTypes a -> b
f  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType ((a -> b) -> a
forall a b. (a -> b) -> a
argTy a -> b
f) Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Reification
forall a. Conjurable a => a -> Reification
conjureType ((a -> b) -> b
forall a b. (a -> b) -> b
resTy a -> b
f)
  conjureIf :: (a -> b) -> Expr
conjureIf a -> b
f  =  b -> Expr
forall a. Conjurable a => a -> Expr
conjureIf (a -> b
f a
forall a. HasCallStack => a
undefined)

argTy :: (a -> b) -> a
argTy :: (a -> b) -> a
argTy a -> b
_  =  a
forall a. HasCallStack => a
undefined

resTy :: (a -> b) -> b
resTy :: (a -> b) -> b
resTy a -> b
_  =  b
forall a. HasCallStack => a
undefined

conjureApplication :: Conjurable f => String -> f -> Expr
conjureApplication :: [Char] -> f -> Expr
conjureApplication  =  ([Char] -> f -> Expr) -> [Char] -> f -> Expr
forall f.
Conjurable f =>
([Char] -> f -> Expr) -> [Char] -> f -> Expr
conjureWhatApplication [Char] -> f -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value

conjureVarApplication :: Conjurable f => String -> f -> Expr
conjureVarApplication :: [Char] -> f -> Expr
conjureVarApplication  =  ([Char] -> f -> Expr) -> [Char] -> f -> Expr
forall f.
Conjurable f =>
([Char] -> f -> Expr) -> [Char] -> f -> Expr
conjureWhatApplication [Char] -> f -> Expr
forall a. Typeable a => [Char] -> a -> Expr
var

conjureWhatApplication :: Conjurable f => (String -> f -> Expr) -> String -> f -> Expr
conjureWhatApplication :: ([Char] -> f -> Expr) -> [Char] -> f -> Expr
conjureWhatApplication [Char] -> f -> Expr
what [Char]
nm f
f  =  Expr -> Expr
mostGeneralCanonicalVariation (Expr -> Expr) -> ([Expr] -> Expr) -> [Expr] -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Expr] -> Expr
foldApp
                                  ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$  [Char] -> f -> Expr
what [Char]
nf f
f Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: ([Char] -> Expr -> Expr) -> [[Char]] -> [Expr] -> [Expr]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith [Char] -> Expr -> Expr
varAsTypeOf [[Char]]
nas (f -> [Expr]
forall a. Conjurable a => a -> [Expr]
conjureArgumentHoles f
f)
  where
  ([Char]
nf:[[Char]]
nas)  =  [Char] -> [[Char]]
words [Char]
nm [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [Char] -> [[Char]]
forall a. a -> [a]
repeat [Char]
""



-- -- -- other Conjurable instances -- -- --

instance Conjurable Ordering where
  conjureEquality :: Ordering -> Maybe Expr
conjureEquality  =  Ordering -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Ordering -> Maybe [[Expr]]
conjureTiers     =  Ordering -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Float where
  conjureEquality :: Float -> Maybe Expr
conjureEquality  =  Float -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Float -> Maybe [[Expr]]
conjureTiers     =  Float -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Double where
  conjureEquality :: Double -> Maybe Expr
conjureEquality  =  Double -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Double -> Maybe [[Expr]]
conjureTiers     =  Double -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Int8 where
  conjureEquality :: Int8 -> Maybe Expr
conjureEquality  =  Int8 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Int8 -> Maybe [[Expr]]
conjureTiers     =  Int8 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Int16 where
  conjureEquality :: Int16 -> Maybe Expr
conjureEquality  =  Int16 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Int16 -> Maybe [[Expr]]
conjureTiers     =  Int16 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Int32 where
  conjureEquality :: Int32 -> Maybe Expr
conjureEquality  =  Int32 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Int32 -> Maybe [[Expr]]
conjureTiers     =  Int32 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Int64 where
  conjureEquality :: Int64 -> Maybe Expr
conjureEquality  =  Int64 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Int64 -> Maybe [[Expr]]
conjureTiers     =  Int64 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Word where
  conjureEquality :: Word -> Maybe Expr
conjureEquality  =  Word -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Word -> Maybe [[Expr]]
conjureTiers     =  Word -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Word8 where
  conjureEquality :: Word8 -> Maybe Expr
conjureEquality  =  Word8 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Word8 -> Maybe [[Expr]]
conjureTiers     =  Word8 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Word16 where
  conjureEquality :: Word16 -> Maybe Expr
conjureEquality  =  Word16 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Word16 -> Maybe [[Expr]]
conjureTiers     =  Word16 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Word32 where
  conjureEquality :: Word32 -> Maybe Expr
conjureEquality  =  Word32 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Word32 -> Maybe [[Expr]]
conjureTiers     =  Word32 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable Word64 where
  conjureEquality :: Word64 -> Maybe Expr
conjureEquality  =  Word64 -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Word64 -> Maybe [[Expr]]
conjureTiers     =  Word64 -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance (Integral a, Conjurable a, Listable a, Show a, Eq a) => Conjurable (Ratio a) where
  conjureEquality :: Ratio a -> Maybe Expr
conjureEquality  =  Ratio a -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Ratio a -> Maybe [[Expr]]
conjureTiers     =  Ratio a -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: Ratio a -> Reification
conjureSubTypes Ratio a
q  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType (Ratio a -> a
forall a. Ratio a -> a
numerator Ratio a
q)

instance (RealFloat a, Conjurable a, Listable a, Show a, Eq a) => Conjurable (Complex a) where
  conjureEquality :: Complex a -> Maybe Expr
conjureEquality  =  Complex a -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: Complex a -> Maybe [[Expr]]
conjureTiers     =  Complex a -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: Complex a -> Reification
conjureSubTypes Complex a
x  =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType (Complex a -> a
forall a. Complex a -> a
realPart Complex a
x)


-- Conjurable helper types --
instance Conjurable A where
  conjureEquality :: A -> Maybe Expr
conjureEquality  =  A -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: A -> Maybe [[Expr]]
conjureTiers     =  A -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable B where
  conjureEquality :: B -> Maybe Expr
conjureEquality  =  B -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: B -> Maybe [[Expr]]
conjureTiers     =  B -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable C where
  conjureEquality :: C -> Maybe Expr
conjureEquality  =  C -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: C -> Maybe [[Expr]]
conjureTiers     =  C -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable D where
  conjureEquality :: D -> Maybe Expr
conjureEquality  =  D -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: D -> Maybe [[Expr]]
conjureTiers     =  D -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable E where
  conjureEquality :: E -> Maybe Expr
conjureEquality  =  E -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: E -> Maybe [[Expr]]
conjureTiers     =  E -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

instance Conjurable F where
  conjureEquality :: F -> Maybe Expr
conjureEquality  =  F -> Maybe Expr
forall a. (Eq a, Typeable a) => a -> Maybe Expr
reifyEquality
  conjureTiers :: F -> Maybe [[Expr]]
conjureTiers     =  F -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers

deriving instance Typeable A -- for GHC < 7.10
deriving instance Typeable B -- for GHC < 7.10
deriving instance Typeable C -- for GHC < 7.10
deriving instance Typeable D -- for GHC < 7.10
deriving instance Typeable E -- for GHC < 7.10
deriving instance Typeable F -- for GHC < 7.10


-- Conjurable tuples --

instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         , Conjurable c, Listable c, Show c
         , Conjurable d, Listable d, Show d
         ) => Conjurable (a,b,c,d) where
  conjureTiers :: (a, b, c, d) -> Maybe [[Expr]]
conjureTiers     =  (a, b, c, d) -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: (a, b, c, d) -> Reification
conjureSubTypes (a, b, c, d)
xyzw =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
x
                       Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  b -> Reification
forall a. Conjurable a => a -> Reification
conjureType b
y
                       Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  c -> Reification
forall a. Conjurable a => a -> Reification
conjureType c
z
                       Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  d -> Reification
forall a. Conjurable a => a -> Reification
conjureType d
w
                       where (a
x,b
y,c
z,d
w) = (a, b, c, d)
xyzw
  conjureEquality :: (a, b, c, d) -> Maybe Expr
conjureEquality (a, b, c, d)
xyzw  =  Expr -> Expr -> Expr -> Expr -> Expr
from
                       (Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
                       Maybe (Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
y
                       Maybe (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> c -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality c
z
                       Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> d -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality d
w
    where
    (a
x,b
y,c
z,d
w)  =  (a, b, c, d)
xyzw
    from :: Expr -> Expr -> Expr -> Expr -> Expr
from Expr
e1 Expr
e2 Expr
e3 Expr
e4  =  [Char] -> ((a, b, c, d) -> (a, b, c, d) -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" (a, b, c, d) -> (a, b, c, d) -> Bool
(==)
      where
      ==... :: a -> a -> Bool
(==...)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e1 (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      .==.. :: b -> b -> Bool
(.==..)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e2 (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
y
      ..==. :: c -> c -> Bool
(..==.)  =  Expr -> c -> c -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e3 (c -> c -> Bool) -> c -> c -> c -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: c
z
      ...== :: d -> d -> Bool
(...==)  =  Expr -> d -> d -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e4 (d -> d -> Bool) -> d -> d -> d -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: d
w
      (a
x1,b
y1,c
z1,d
w1) == :: (a, b, c, d) -> (a, b, c, d) -> Bool
== (a
x2,b
y2,c
z2,d
w2)  =  a
x1 a -> a -> Bool
==... a
x2
                                      Bool -> Bool -> Bool
&& b
y1 b -> b -> Bool
.==.. b
y2
                                      Bool -> Bool -> Bool
&& c
z1 c -> c -> Bool
..==. c
z2
                                      Bool -> Bool -> Bool
&& d
w1 d -> d -> Bool
...== d
w2

instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         , Conjurable c, Listable c, Show c
         , Conjurable d, Listable d, Show d
         , Conjurable e, Listable e, Show e
         ) => Conjurable (a,b,c,d,e) where
  conjureTiers :: (a, b, c, d, e) -> Maybe [[Expr]]
conjureTiers     =  (a, b, c, d, e) -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: (a, b, c, d, e) -> Reification
conjureSubTypes (a, b, c, d, e)
xyzwv =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
x
                        Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  b -> Reification
forall a. Conjurable a => a -> Reification
conjureType b
y
                        Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  c -> Reification
forall a. Conjurable a => a -> Reification
conjureType c
z
                        Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  d -> Reification
forall a. Conjurable a => a -> Reification
conjureType d
w
                        Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  e -> Reification
forall a. Conjurable a => a -> Reification
conjureType e
v
                        where (a
x,b
y,c
z,d
w,e
v) = (a, b, c, d, e)
xyzwv
  conjureEquality :: (a, b, c, d, e) -> Maybe Expr
conjureEquality (a, b, c, d, e)
xyzwv  =  Expr -> Expr -> Expr -> Expr -> Expr -> Expr
from
                        (Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
                        Maybe (Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
y
                        Maybe (Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> c -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality c
z
                        Maybe (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> d -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality d
w
                        Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> e -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality e
v
    where
    (a
x,b
y,c
z,d
w,e
v)  =  (a, b, c, d, e)
xyzwv
    from :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr
from Expr
e1 Expr
e2 Expr
e3 Expr
e4 Expr
e5  =  [Char] -> ((a, b, c, d, e) -> (a, b, c, d, e) -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" (a, b, c, d, e) -> (a, b, c, d, e) -> Bool
(==)
      where
      ==.... :: a -> a -> Bool
(==....)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e1 (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      .==... :: b -> b -> Bool
(.==...)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e2 (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
y
      ..==.. :: c -> c -> Bool
(..==..)  =  Expr -> c -> c -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e3 (c -> c -> Bool) -> c -> c -> c -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: c
z
      ...==. :: d -> d -> Bool
(...==.)  =  Expr -> d -> d -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e4 (d -> d -> Bool) -> d -> d -> d -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: d
w
      ....== :: e -> e -> Bool
(....==)  =  Expr -> e -> e -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e5 (e -> e -> Bool) -> e -> e -> e -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: e
v
      (a
x1,b
y1,c
z1,d
w1,e
v1) == :: (a, b, c, d, e) -> (a, b, c, d, e) -> Bool
== (a
x2,b
y2,c
z2,d
w2,e
v2)  =  a
x1 a -> a -> Bool
==.... a
x2
                                            Bool -> Bool -> Bool
&& b
y1 b -> b -> Bool
.==... b
y2
                                            Bool -> Bool -> Bool
&& c
z1 c -> c -> Bool
..==.. c
z2
                                            Bool -> Bool -> Bool
&& d
w1 d -> d -> Bool
...==. d
w2
                                            Bool -> Bool -> Bool
&& e
v1 e -> e -> Bool
....== e
v2

instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         , Conjurable c, Listable c, Show c
         , Conjurable d, Listable d, Show d
         , Conjurable e, Listable e, Show e
         , Conjurable f, Listable f, Show f
         ) => Conjurable (a,b,c,d,e,f) where
  conjureTiers :: (a, b, c, d, e, f) -> Maybe [[Expr]]
conjureTiers     =  (a, b, c, d, e, f) -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: (a, b, c, d, e, f) -> Reification
conjureSubTypes (a, b, c, d, e, f)
xyzwvu =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
x
                         Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  b -> Reification
forall a. Conjurable a => a -> Reification
conjureType b
y
                         Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  c -> Reification
forall a. Conjurable a => a -> Reification
conjureType c
z
                         Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  d -> Reification
forall a. Conjurable a => a -> Reification
conjureType d
w
                         Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  e -> Reification
forall a. Conjurable a => a -> Reification
conjureType e
v
                         Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  f -> Reification
forall a. Conjurable a => a -> Reification
conjureType f
u
                         where (a
x,b
y,c
z,d
w,e
v,f
u) = (a, b, c, d, e, f)
xyzwvu
  conjureEquality :: (a, b, c, d, e, f) -> Maybe Expr
conjureEquality (a, b, c, d, e, f)
xyzwvu  =  Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
from
                         (Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr
-> Maybe (Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
                         Maybe (Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
y
                         Maybe (Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> c -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality c
z
                         Maybe (Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> d -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality d
w
                         Maybe (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> e -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality e
v
                         Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality f
u
    where
    (a
x,b
y,c
z,d
w,e
v,f
u)  =  (a, b, c, d, e, f)
xyzwvu
    from :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
from Expr
e1 Expr
e2 Expr
e3 Expr
e4 Expr
e5 Expr
e6  =  [Char]
-> ((a, b, c, d, e, f) -> (a, b, c, d, e, f) -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" (a, b, c, d, e, f) -> (a, b, c, d, e, f) -> Bool
(==)
      where
      ==..... :: a -> a -> Bool
(==.....)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e1 (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      .==.... :: b -> b -> Bool
(.==....)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e2 (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
y
      ..==... :: c -> c -> Bool
(..==...)  =  Expr -> c -> c -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e3 (c -> c -> Bool) -> c -> c -> c -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: c
z
      ...==.. :: d -> d -> Bool
(...==..)  =  Expr -> d -> d -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e4 (d -> d -> Bool) -> d -> d -> d -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: d
w
      ....==. :: e -> e -> Bool
(....==.)  =  Expr -> e -> e -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e5 (e -> e -> Bool) -> e -> e -> e -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: e
v
      .....== :: f -> f -> Bool
(.....==)  =  Expr -> f -> f -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e6 (f -> f -> Bool) -> f -> f -> f -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: f
u
      (a
x1,b
y1,c
z1,d
w1,e
v1,f
u1) == :: (a, b, c, d, e, f) -> (a, b, c, d, e, f) -> Bool
== (a
x2,b
y2,c
z2,d
w2,e
v2,f
u2)  =  a
x1 a -> a -> Bool
==..... a
x2
                                                  Bool -> Bool -> Bool
&& b
y1 b -> b -> Bool
.==.... b
y2
                                                  Bool -> Bool -> Bool
&& c
z1 c -> c -> Bool
..==... c
z2
                                                  Bool -> Bool -> Bool
&& d
w1 d -> d -> Bool
...==.. d
w2
                                                  Bool -> Bool -> Bool
&& e
v1 e -> e -> Bool
....==. e
v2
                                                  Bool -> Bool -> Bool
&& f
u1 f -> f -> Bool
.....== f
u2

instance ( Conjurable a, Listable a, Show a
         , Conjurable b, Listable b, Show b
         , Conjurable c, Listable c, Show c
         , Conjurable d, Listable d, Show d
         , Conjurable e, Listable e, Show e
         , Conjurable f, Listable f, Show f
         , Conjurable g, Listable g, Show g
         ) => Conjurable (a,b,c,d,e,f,g) where
  conjureTiers :: (a, b, c, d, e, f, g) -> Maybe [[Expr]]
conjureTiers     =  (a, b, c, d, e, f, g) -> Maybe [[Expr]]
forall a. (Listable a, Show a, Typeable a) => a -> Maybe [[Expr]]
reifyTiers
  conjureSubTypes :: (a, b, c, d, e, f, g) -> Reification
conjureSubTypes (a, b, c, d, e, f, g)
xyzwvut =  a -> Reification
forall a. Conjurable a => a -> Reification
conjureType a
x
                          Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  b -> Reification
forall a. Conjurable a => a -> Reification
conjureType b
y
                          Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  c -> Reification
forall a. Conjurable a => a -> Reification
conjureType c
z
                          Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  d -> Reification
forall a. Conjurable a => a -> Reification
conjureType d
w
                          Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  e -> Reification
forall a. Conjurable a => a -> Reification
conjureType e
v
                          Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  f -> Reification
forall a. Conjurable a => a -> Reification
conjureType f
u
                          Reification -> Reification -> Reification
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  g -> Reification
forall a. Conjurable a => a -> Reification
conjureType g
t
                         where (a
x,b
y,c
z,d
w,e
v,f
u,g
t) = (a, b, c, d, e, f, g)
xyzwvut
  conjureEquality :: (a, b, c, d, e, f, g) -> Maybe Expr
conjureEquality (a, b, c, d, e, f, g)
xyzwvut  =  Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
from
                          (Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr
-> Maybe (Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality a
x
                          Maybe (Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr
-> Maybe (Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> b -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality b
y
                          Maybe (Expr -> Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> c -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality c
z
                          Maybe (Expr -> Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> d -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality d
w
                          Maybe (Expr -> Expr -> Expr -> Expr)
-> Maybe Expr -> Maybe (Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> e -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality e
v
                          Maybe (Expr -> Expr -> Expr) -> Maybe Expr -> Maybe (Expr -> Expr)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> f -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality f
u
                          Maybe (Expr -> Expr) -> Maybe Expr -> Maybe Expr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> g -> Maybe Expr
forall a. Conjurable a => a -> Maybe Expr
conjureEquality g
t
    where
    (a
x,b
y,c
z,d
w,e
v,f
u,g
t)  =  (a, b, c, d, e, f, g)
xyzwvut
    from :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Expr
from Expr
e1 Expr
e2 Expr
e3 Expr
e4 Expr
e5 Expr
e6 Expr
e7  =  [Char]
-> ((a, b, c, d, e, f, g) -> (a, b, c, d, e, f, g) -> Bool) -> Expr
forall a. Typeable a => [Char] -> a -> Expr
value [Char]
"==" (a, b, c, d, e, f, g) -> (a, b, c, d, e, f, g) -> Bool
(==)
      where
      ==...... :: a -> a -> Bool
(==......)  =  Expr -> a -> a -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e1 (a -> a -> Bool) -> a -> a -> a -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: a
x
      .==..... :: b -> b -> Bool
(.==.....)  =  Expr -> b -> b -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e2 (b -> b -> Bool) -> b -> b -> b -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: b
y
      ..==.... :: c -> c -> Bool
(..==....)  =  Expr -> c -> c -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e3 (c -> c -> Bool) -> c -> c -> c -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: c
z
      ...==... :: d -> d -> Bool
(...==...)  =  Expr -> d -> d -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e4 (d -> d -> Bool) -> d -> d -> d -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: d
w
      ....==.. :: e -> e -> Bool
(....==..)  =  Expr -> e -> e -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e5 (e -> e -> Bool) -> e -> e -> e -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: e
v
      .....==. :: f -> f -> Bool
(.....==.)  =  Expr -> f -> f -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e6 (f -> f -> Bool) -> f -> f -> f -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: f
u
      ......== :: g -> g -> Bool
(......==)  =  Expr -> g -> g -> Bool
forall a. Typeable a => Expr -> a
evl Expr
e7 (g -> g -> Bool) -> g -> g -> g -> Bool
forall a. (a -> a -> Bool) -> a -> a -> a -> Bool
==: g
t
      (a
x1,b
y1,c
z1,d
w1,e
v1,f
u1,g
t1) == :: (a, b, c, d, e, f, g) -> (a, b, c, d, e, f, g) -> Bool
== (a
x2,b
y2,c
z2,d
w2,e
v2,f
u2,g
t2)  =  a
x1 a -> a -> Bool
==...... a
x2
                                                        Bool -> Bool -> Bool
&& b
y1 b -> b -> Bool
.==..... b
y2
                                                        Bool -> Bool -> Bool
&& c
z1 c -> c -> Bool
..==.... c
z2
                                                        Bool -> Bool -> Bool
&& d
w1 d -> d -> Bool
...==... d
w2
                                                        Bool -> Bool -> Bool
&& e
v1 e -> e -> Bool
....==.. e
v2
                                                        Bool -> Bool -> Bool
&& f
u1 f -> f -> Bool
.....==. f
u2
                                                        Bool -> Bool -> Bool
&& g
t1 g -> g -> Bool
......== g
t2

-- TODO: go up to 12-tuples