recover-rtti (empty) → 0.1.0.0
raw patch · 27 files changed
+4646/−0 lines, 27 filesdep +QuickCheckdep +aesondep +base
Dependencies added: QuickCheck, aeson, base, bytestring, containers, ghc-heap, ghc-prim, mtl, recover-rtti, sop-core, stm, tasty, tasty-quickcheck, text, vector
Files
- CHANGELOG.md +5/−0
- LICENSE +31/−0
- README.md +33/−0
- recover-rtti.cabal +87/−0
- src/Debug/RecoverRTTI.hs +10/−0
- src/Debug/RecoverRTTI/Classifier.hs +143/−0
- src/Debug/RecoverRTTI/Classify.hs +562/−0
- src/Debug/RecoverRTTI/ClosureTree.hs +25/−0
- src/Debug/RecoverRTTI/Constr.hs +183/−0
- src/Debug/RecoverRTTI/FlatClosure.hs +89/−0
- src/Debug/RecoverRTTI/Modules.hs +191/−0
- src/Debug/RecoverRTTI/Tuple.hs +152/−0
- src/Debug/RecoverRTTI/Tuple/Recursive.hs +429/−0
- src/Debug/RecoverRTTI/Tuple/Size.hs +517/−0
- src/Debug/RecoverRTTI/UserDefined.hs +71/−0
- src/Debug/RecoverRTTI/Util.hs +111/−0
- src/Debug/RecoverRTTI/Util/TypeLevel.hs +166/−0
- src/Debug/RecoverRTTI/Wrappers.hs +70/−0
- tests/RecoverRttiTests.hs +17/−0
- tests/Test/RecoverRTTI/Arbitrary.hs +603/−0
- tests/Test/RecoverRTTI/Classify.hs +232/−0
- tests/Test/RecoverRTTI/ConcreteClassifier.hs +428/−0
- tests/Test/RecoverRTTI/Orphans.hs +14/−0
- tests/Test/RecoverRTTI/Sanity.hs +24/−0
- tests/Test/RecoverRTTI/Show.hs +34/−0
- tests/Test/RecoverRTTI/Staged.hs +340/−0
- tests/Test/RecoverRTTI/UserDefined.hs +79/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for recover-rtti++## 0.1.0.0 -- 2021-03-11++* Alpha release
+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) 2021, Juspay Technologies Pvt Ltd, Well-Typed LLP++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Juspay Technologies, nor Well-Typed LLP,+ nor the names of other contributors may be used to endorse or promote+ products derived from this software without specific prior written+ permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,33 @@+# recover-rtti++Recover run-time type information from the GHC heap. The key function in this+library is++```haskell+classify :: a -> Classifier a+```++which recovers type information about values about which we know nothing (in+particular, no type class constraints). One example use case is the following+`anythingToString` function:++```haskell+anythingToString :: a -> String+```+++We test that the result of `anythingToString` is equal to the result of regular+`show` for a large range of data types (including user-defined ones that the+library is not aware of). There are also other possible use cases; for example,+it should be possible to define an `anythingToJSON` function.++Obviously there are limitations; the most important ones are:++* `UNPACK`ed fields are invisible to the library. This does not need to be+ a major issue though, when compiling code with `-O0` fields are not unpacked.+ (https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/exts/pragmas.html?highlight=unpack#nounpack-pragma)+* Record field names are not known, and so records are shown just using the+ constructor.++There may be other gotchas as well; this library is primarily intended+for debugging.
+ recover-rtti.cabal view
@@ -0,0 +1,87 @@+cabal-version: 2.4+name: recover-rtti+version: 0.1.0.0+synopsis: Recover run-time type information from the GHC heap+description: The main function in this package is 'classify', which looks+ at the GHC heap to recover type information about arbitrary+ values. This makes it possible for example to show any value+ (function 'anythingToString') without having any @Show@+ instance in scope, though there are other use cases as well.+ For example, you could use it to define an 'anythingToJSON'+ function.+bug-reports: https://github.com/well-typed/recover-rtti/issues+license: BSD-3-Clause+license-file: LICENSE+author: Edsko de Vries+maintainer: edsko@well-typed.com+copyright: Juspay Technologies Pvt Ltd, Well-Typed LLP+category: Debugging+extra-source-files:+ README.md+ CHANGELOG.md++Tested-With: GHC ==8.8.4 || ==8.10.4 || ==9.0.1++library+ exposed-modules: Debug.RecoverRTTI++ -- Other modules exported primarily for the tests+ Debug.RecoverRTTI.FlatClosure+ Debug.RecoverRTTI.Util+ Debug.RecoverRTTI.Util.TypeLevel++ other-modules: Debug.RecoverRTTI.Classifier+ Debug.RecoverRTTI.Classify+ Debug.RecoverRTTI.ClosureTree+ Debug.RecoverRTTI.Constr+ Debug.RecoverRTTI.Modules+ Debug.RecoverRTTI.Tuple+ Debug.RecoverRTTI.Tuple.Recursive+ Debug.RecoverRTTI.Tuple.Size+ Debug.RecoverRTTI.UserDefined+ Debug.RecoverRTTI.Wrappers+ build-depends: base >= 4.13 && < 4.16+ , aeson >= 1.5 && < 1.6+ , bytestring >= 0.10 && < 0.11+ , containers >= 0.6 && < 0.7+ , ghc-heap >= 8.8 && < 9.1+ , mtl >= 2.2 && < 2.3+ , sop-core >= 0.5 && < 0.6+ , stm >= 2.5 && < 2.6+ , text >= 1.2 && < 1.3+ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall+ -Wredundant-constraints++test-suite test-recover-rtti+ default-language: Haskell2010+ type: exitcode-stdio-1.0+ hs-source-dirs: tests+ main-is: RecoverRttiTests.hs+ other-modules: Test.RecoverRTTI.Arbitrary+ Test.RecoverRTTI.Classify+ Test.RecoverRTTI.ConcreteClassifier+ Test.RecoverRTTI.Orphans+ Test.RecoverRTTI.Show+ Test.RecoverRTTI.Sanity+ Test.RecoverRTTI.Staged+ Test.RecoverRTTI.UserDefined+ build-depends: base >= 4.13+ , recover-rtti++ , aeson+ , bytestring+ , containers+ , ghc-heap+ , ghc-prim+ , mtl+ , QuickCheck+ , sop-core+ , stm+ , tasty+ , tasty-quickcheck+ , text+ , vector+ ghc-options: -Wall+ -Wno-orphans
+ src/Debug/RecoverRTTI.hs view
@@ -0,0 +1,10 @@+module Debug.RecoverRTTI (+ module X+ ) where++import Debug.RecoverRTTI.Classifier as X+import Debug.RecoverRTTI.Classify as X+import Debug.RecoverRTTI.Constr as X+import Debug.RecoverRTTI.UserDefined as X+import Debug.RecoverRTTI.Wrappers as X+import Debug.RecoverRTTI.Tuple as X
+ src/Debug/RecoverRTTI/Classifier.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE StandaloneDeriving #-}++module Debug.RecoverRTTI.Classifier (+ Classifier(..)+ , Classifiers(..)+ , Classified(..)+ -- * Partial information+ , MaybeF(..)+ , EitherF(..)+ , MaybePairF(..)+ ) where++import Data.Aeson (Value)+import Data.Int+import Data.IntMap (IntMap)+import Data.IntSet (IntSet)+import Data.Kind+import Data.Map (Map)+import Data.Ratio+import Data.Sequence (Seq)+import Data.Set (Set)+import Data.SOP+import Data.Tree (Tree)+import Data.Void+import Data.Word++import qualified Data.ByteString as BS.Strict+import qualified Data.ByteString.Lazy as BS.Lazy+import qualified Data.ByteString.Short as BS.Short+import qualified Data.Text as Text.Strict+import qualified Data.Text.Lazy as Text.Lazy++import Debug.RecoverRTTI.Constr+import Debug.RecoverRTTI.Tuple+import Debug.RecoverRTTI.UserDefined+import Debug.RecoverRTTI.Wrappers+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Classifier+-------------------------------------------------------------------------------}++-- | A value along with its classifier+data Classified a = Classified {+ classifiedType :: Classifier a+ , classifiedValue :: a+ }++-- | Classifier+--+-- Given a value of some unknown type @a@, a @Classifier a@ will tell you what+-- the type of @a@ is. This is similar to a @TypeRep@, but since we recover+-- this information from the heap, we have less accurate type information than+-- @TypeRep@ does.+data Classifier (a :: Type) :: Type where+ -- Primitive types++ C_Bool :: Classifier Bool+ C_Char :: Classifier Char+ C_Double :: Classifier Double+ C_Float :: Classifier Float+ C_Int :: Classifier Int+ C_Int16 :: Classifier Int16+ C_Int8 :: Classifier Int8+ C_Int32 :: Classifier Int32+ C_Int64 :: Classifier Int64+ C_Integer :: Classifier Integer+ C_Ordering :: Classifier Ordering+ C_Unit :: Classifier ()+ C_Word :: Classifier Word+ C_Word8 :: Classifier Word8+ C_Word16 :: Classifier Word16+ C_Word32 :: Classifier Word32+ C_Word64 :: Classifier Word64++ -- String types+ --+ -- We list @String@ separately, so that we show them properly (rather than+ -- as a list of characters). Of course, empty strings will be inferred as+ -- empty lists instead.++ C_String :: Classifier String+ C_BS_Strict :: Classifier BS.Strict.ByteString+ C_BS_Lazy :: Classifier BS.Lazy.ByteString+ C_BS_Short :: Classifier BS.Short.ShortByteString+ C_Text_Strict :: Classifier Text.Strict.Text+ C_Text_Lazy :: Classifier Text.Lazy.Text++ -- Aeson++ C_Value :: Classifier Value++ -- Compound++ C_Maybe :: MaybeF Classified a -> Classifier (Maybe a)+ C_Either :: EitherF Classified a b -> Classifier (Either a b)+ C_List :: MaybeF Classified a -> Classifier [a]+ C_Ratio :: Classified a -> Classifier (Ratio a)+ C_Set :: MaybeF Classified a -> Classifier (Set a)+ C_Map :: MaybePairF Classified a b -> Classifier (Map a b)+ C_IntSet :: Classifier IntSet+ C_IntMap :: MaybeF Classified a -> Classifier (IntMap a)+ C_Sequence :: MaybeF Classified a -> Classifier (Seq a)+ C_Tree :: Classified a -> Classifier (Tree a)++ C_Tuple ::+ (SListI xs, IsValidSize (Length xs))+ => Classifiers xs -> Classifier (WrappedTuple xs)++ -- Reference cells++ C_STRef :: Classifier SomeSTRef+ C_TVar :: Classifier SomeTVar+ C_MVar :: Classifier SomeMVar++ -- Functions++ C_Fun :: Classifier SomeFun++ -- User-defined++ C_Custom :: Sing c -> Classifier (UserDefined c)++newtype Classifiers xs = Classifiers (NP Classified xs)++{-------------------------------------------------------------------------------+ Partial information+-------------------------------------------------------------------------------}++data MaybeF f a where+ FNothing :: MaybeF f Void+ FJust :: f a -> MaybeF f a++data EitherF f a b where+ FLeft :: f a -> EitherF f a Void+ FRight :: f b -> EitherF f Void b++data MaybePairF f a b where+ FNothingPair :: MaybePairF f Void Void+ FJustPair :: f a -> f b -> MaybePairF f a b
+ src/Debug/RecoverRTTI/Classify.hs view
@@ -0,0 +1,562 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Debug.RecoverRTTI.Classify (+ -- * Classification+ classify+ , classified+ , fromUserDefined+ -- * Showing values+ , anythingToString+ , canShowClassified+ ) where++import Control.Monad.Except+import Data.IntMap (IntMap)+import Data.Map (Map)+import Data.Sequence (Seq)+import Data.Set (Set)+import Data.SOP+import Data.SOP.Dict+import Data.Tree (Tree)+import GHC.Real+import GHC.Stack+import GHC.Exts.Heap (Closure)+import System.IO.Unsafe (unsafePerformIO)+import Unsafe.Coerce (unsafeCoerce)++import qualified Data.IntMap as IntMap+import qualified Data.Map as Map+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Tree as Tree++import Debug.RecoverRTTI.Classifier+import Debug.RecoverRTTI.Constr+import Debug.RecoverRTTI.FlatClosure+import Debug.RecoverRTTI.Modules+import Debug.RecoverRTTI.Tuple+import Debug.RecoverRTTI.UserDefined+import Debug.RecoverRTTI.Util+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Classification+-------------------------------------------------------------------------------}++classifyIO :: a -> ExceptT Closure IO (Classifier a)+classifyIO x = do+ closure <- lift $ getBoxedClosureData (asBox x)+ case closure of+ --+ -- Primitive (ghc-prim)+ --++ -- GHC.Types+ (inKnownModule GhcTypes -> Just "True") -> return $ mustBe C_Bool+ (inKnownModule GhcTypes -> Just "False") -> return $ mustBe C_Bool+ (inKnownModule GhcTypes -> Just "C#") -> return $ mustBe C_Char+ (inKnownModule GhcTypes -> Just "D#") -> return $ mustBe C_Double+ (inKnownModule GhcTypes -> Just "F#") -> return $ mustBe C_Float+ (inKnownModule GhcTypes -> Just "I#") -> return $ mustBe C_Int+ (inKnownModule GhcTypes -> Just "LT") -> return $ mustBe C_Ordering+ (inKnownModule GhcTypes -> Just "GT") -> return $ mustBe C_Ordering+ (inKnownModule GhcTypes -> Just "EQ") -> return $ mustBe C_Ordering+ (inKnownModule GhcTypes -> Just "W#") -> return $ mustBe C_Word++ -- GHC.Tuple+ (inKnownModule GhcTuple -> Just "()") -> return $ mustBe C_Unit++ -- GHC.Int+ (inKnownModule GhcInt -> Just "I8#") -> return $ mustBe C_Int8+ (inKnownModule GhcInt -> Just "I16#") -> return $ mustBe C_Int16+ (inKnownModule GhcInt -> Just "I32#") -> return $ mustBe C_Int32+ (inKnownModule GhcInt -> Just "I64#") -> return $ mustBe C_Int64++ -- GHC.Integer+ (inKnownModule GhcIntegerType -> Just "S#") -> return $ mustBe C_Integer+ (inKnownModule GhcIntegerType -> Just "Jp#") -> return $ mustBe C_Integer+ (inKnownModule GhcIntegerType -> Just "Jn#") -> return $ mustBe C_Integer+ (inKnownModule GhcNumInteger -> Just "IS") -> return $ mustBe C_Integer+ (inKnownModule GhcNumInteger -> Just "IP") -> return $ mustBe C_Integer+ (inKnownModule GhcNumInteger -> Just "IN") -> return $ mustBe C_Integer++ -- GHC.Word+ (inKnownModule GhcWord -> Just "W8#") -> return $ mustBe C_Word8+ (inKnownModule GhcWord -> Just "W16#") -> return $ mustBe C_Word16+ (inKnownModule GhcWord -> Just "W32#") -> return $ mustBe C_Word32+ (inKnownModule GhcWord -> Just "W64#") -> return $ mustBe C_Word64++ --+ -- String types+ --++ -- bytestring+ (inKnownModule DataByteStringInternal -> Just "PS") -> return $ mustBe C_BS_Strict+ (inKnownModule DataByteStringLazyInternal -> Just "Empty") -> return $ mustBe C_BS_Lazy+ (inKnownModule DataByteStringLazyInternal -> Just "Chunk") -> return $ mustBe C_BS_Lazy+ (inKnownModule DataByteStringShortInternal -> Just "SBS") -> return $ mustBe C_BS_Short++ -- text+ (inKnownModule DataTextInternal -> Just "Text") -> return $ mustBe C_Text_Strict+ (inKnownModule DataTextInternalLazy -> Just "Chunk") -> return $ mustBe C_Text_Lazy+ (inKnownModule DataTextInternalLazy -> Just "Empty") -> return $ mustBe C_Text_Lazy++ --+ -- Aeson+ --++ (inKnownModule DataAesonTypesInternal -> Just "Object") -> return $ mustBe C_Value+ (inKnownModule DataAesonTypesInternal -> Just "Array") -> return $ mustBe C_Value+ (inKnownModule DataAesonTypesInternal -> Just "String") -> return $ mustBe C_Value+ (inKnownModule DataAesonTypesInternal -> Just "Number") -> return $ mustBe C_Value+ (inKnownModule DataAesonTypesInternal -> Just "Bool") -> return $ mustBe C_Value+ (inKnownModule DataAesonTypesInternal -> Just "Null") -> return $ mustBe C_Value++ --+ -- Compound (ghc-prim)+ --++ -- Maybe+ (inKnownModule GhcMaybe -> Just "Nothing") ->+ mustBe <$> classifyMaybe (unsafeCoerce x)+ (inKnownModule GhcMaybe -> Just "Just") ->+ mustBe <$> classifyMaybe (unsafeCoerce x)++ -- Either+ (inKnownModule DataEither -> Just "Left") ->+ mustBe <$> classifyEither (unsafeCoerce x)+ (inKnownModule DataEither -> Just "Right") ->+ mustBe <$> classifyEither (unsafeCoerce x)++ -- Lists (this includes the 'String' case)+ (inKnownModule GhcTypes -> Just "[]") ->+ mustBe <$> classifyList (unsafeCoerce x)+ (inKnownModule GhcTypes -> Just ":") ->+ mustBe <$> classifyList (unsafeCoerce x)++ -- Ratio+ (inKnownModule GhcReal -> Just ":%") ->+ mustBe <$> classifyRatio (unsafeCoerce x)++ -- Set+ (inKnownModule DataSetInternal -> Just "Tip") ->+ mustBe <$> classifySet (unsafeCoerce x)+ (inKnownModule DataSetInternal -> Just "Bin") ->+ mustBe <$> classifySet (unsafeCoerce x)++ -- Map+ (inKnownModule DataMapInternal -> Just "Tip") ->+ mustBe <$> classifyMap (unsafeCoerce x)+ (inKnownModule DataMapInternal -> Just "Bin") ->+ mustBe <$> classifyMap (unsafeCoerce x)++ -- IntSet+ (inKnownModule DataIntSetInternal -> Just "Bin") ->+ return $ mustBe $ C_IntSet+ (inKnownModule DataIntSetInternal -> Just "Tip") ->+ return $ mustBe $ C_IntSet+ (inKnownModule DataIntSetInternal -> Just "Nil") ->+ return $ mustBe $ C_IntSet++ -- IntMap+ (inKnownModule DataIntMapInternal -> Just "Nil") ->+ mustBe <$> classifyIntMap (unsafeCoerce x)+ (inKnownModule DataIntMapInternal -> Just "Tip") ->+ mustBe <$> classifyIntMap (unsafeCoerce x)+ (inKnownModule DataIntMapInternal -> Just "Bin") ->+ mustBe <$> classifyIntMap (unsafeCoerce x)++ -- Sequence+ (inKnownModule DataSequenceInternal -> Just "EmptyT") ->+ mustBe <$> classifySequence (unsafeCoerce x)+ (inKnownModule DataSequenceInternal -> Just "Single") ->+ mustBe <$> classifySequence (unsafeCoerce x)+ (inKnownModule DataSequenceInternal -> Just "Deep") ->+ mustBe <$> classifySequence (unsafeCoerce x)++ -- Tree+ (inKnownModule DataTree -> Just "Node") ->+ mustBe <$> classifyTree (unsafeCoerce x)++ -- Tuples (of size 2..62)+ (inKnownModuleNested GhcTuple -> Just (+ isTuple -> Just (Some validSize@(ValidSize sz _))+ , verifySize sz -> Just (VerifiedSize ptrs)+ )) ->+ case liftValidSize validSize of+ Dict -> mustBe <$> classifyTuple ptrs++ --+ -- Reference cells+ --++ (inKnownModule GhcSTRef -> Just "STRef") -> return $ mustBe C_STRef+ (inKnownModule GhcMVar -> Just "MVar") -> return $ mustBe C_MVar+ (inKnownModule GhcConcSync -> Just "TVar") -> return $ mustBe C_TVar++ --+ -- Functions+ --++ FunClosure {} -> return $ mustBe C_Fun++ --+ -- User defined+ --++ ConstrClosure {pkg, modl, name} ->+ elimKnownConstr (Constr pkg modl name) $ \p ->+ return $ mustBe (C_Custom p)++ --+ -- Classification failed+ --++ OtherClosure other -> ExceptT $ return (Left other)++mustBe :: Classifier b -> Classifier a+mustBe = unsafeCoerce++-- | Classify a value+--+-- Given a value of some unknown type @a@ and a classifier @Classifier a@,+-- it should be sound to coerce the value to the type indicated by the+-- classifier.+--+-- This is also the reason not all values can be classified; in particular,+-- we cannot classify values of unlifted types, as for these types coercion+-- does not work (this would result in a ghc runtime crash).+classify :: a -> Either Closure (Classifier a)+classify = unsafePerformIO . runExceptT . classifyIO++{-------------------------------------------------------------------------------+ Classification for compound types+-------------------------------------------------------------------------------}++classifyMaybe :: Maybe a -> ExceptT Closure IO (Classifier (Maybe a))+classifyMaybe x =+ case x of+ Nothing -> return $ mustBe $ C_Maybe FNothing+ Just x' -> do+ cx <- classifyIO x'+ return $ mustBe $ C_Maybe (FJust (Classified cx x'))++classifyEither :: Either a b -> ExceptT Closure IO (Classifier (Either a b))+classifyEither x =+ case x of+ Left x' -> do+ cx <- classifyIO x'+ return $ mustBe $ C_Either (FLeft (Classified cx x'))+ Right y' -> do+ cy <- classifyIO y'+ return $ mustBe $ C_Either (FRight (Classified cy y'))++classifyList :: [a] -> ExceptT Closure IO (Classifier [a])+classifyList x =+ case x of+ [] -> return $ mustBe $ C_List FNothing+ x':_ -> do+ cx <- classifyIO x'+ return $ case cx of+ C_Char -> mustBe $ C_String+ _otherwise -> mustBe $ C_List (FJust (Classified cx x'))++classifyRatio :: Ratio a -> ExceptT Closure IO (Classifier (Ratio a))+classifyRatio (x' :% _) = do+ cx <- classifyIO x'+ return $ mustBe $ C_Ratio (Classified cx x')++classifySet :: Set a -> ExceptT Closure IO (Classifier (Set a))+classifySet x =+ case Set.lookupMin x of+ Nothing -> return $ mustBe $ C_Set FNothing+ Just x' -> do+ cx <- classifyIO x'+ return $ mustBe $ C_Set (FJust (Classified cx x'))++classifyMap :: Map a b -> ExceptT Closure IO (Classifier (Map a b))+classifyMap x =+ case Map.lookupMin x of+ Nothing -> return $ mustBe $ C_Map FNothingPair+ Just (x', y') -> do+ cx <- classifyIO x'+ cy <- classifyIO y'+ return $ mustBe $ C_Map (FJustPair (Classified cx x') (Classified cy y'))++classifyIntMap :: IntMap a -> ExceptT Closure IO (Classifier (IntMap a))+classifyIntMap x =+ case IntMap.minView x of+ Nothing -> return $ mustBe $ C_IntMap FNothing+ Just (x', _) -> do+ cx <- classifyIO x'+ return $ mustBe $ C_IntMap (FJust (Classified cx x'))++classifySequence :: Seq a -> ExceptT Closure IO (Classifier (Seq a))+classifySequence x =+ case Seq.viewl x of+ Seq.EmptyL -> return $ mustBe $ C_Sequence FNothing+ x' Seq.:< _ -> do+ cx <- classifyIO x'+ return $ mustBe $ C_Sequence (FJust (Classified cx x'))++classifyTree :: Tree a -> ExceptT Closure IO (Classifier (Tree a))+classifyTree x =+ case x of+ Tree.Node x' _ -> do+ cx <- classifyIO x'+ return $ mustBe $ C_Tree (Classified cx x')++classifyTuple ::+ (SListI xs, IsValidSize (Length xs))+ => NP (K Box) xs+ -> ExceptT Closure IO (Classifier (WrappedTuple xs))+classifyTuple ptrs = do+ cs <- hsequence' (hmap aux ptrs)+ return $ C_Tuple (Classifiers cs)+ where+ aux :: K Box a -> (ExceptT Closure IO :.: Classified) a+ aux (K (Box x)) = Comp $ do+ c <- classifyIO (unsafeCoerce x)+ return $ Classified c (unsafeCoerce x)++{-------------------------------------------------------------------------------+ Recognizing tuples+-------------------------------------------------------------------------------}++isTuple :: String -> Maybe (Some ValidSize)+isTuple typ = do+ (a, xs, z) <- dropEnds typ+ guard $ a == '(' && all (== ',') xs && z == ')'+ toValidSize (length xs + 1)++{-------------------------------------------------------------------------------+ Classified values+-------------------------------------------------------------------------------}++classified :: a -> Either Closure (Classified a)+classified x = (\cx -> Classified cx x) <$> classify x++{-------------------------------------------------------------------------------+ Classify constructor arguments+-------------------------------------------------------------------------------}++-- | Classify the arguments to the constructor+--+-- We only look at pointers and ignore any @UNPACK@ed data. Arguments we cannot+-- classify (like unlifted arguments) will be ignored.+fromUserDefined :: forall c.+ (HasCallStack, KnownConstr c)+ => UserDefined c -> [Some Classified]+fromUserDefined = \(UserDefined x) -> unsafePerformIO $ go x+ where+ go :: x -> IO [Some Classified]+ go x = do+ closure <- getBoxedClosureData (asBox x)+ case closure of+ ConstrClosure {pkg, modl, name, ptrArgs} -> do+ let expected, actual :: Constr String+ expected = knownConstr (sing @_ @c)+ actual = Constr pkg modl name+ if expected == actual then do+ goArgs [] ptrArgs+ else do+-- tree <- showClosureTree 5 x+ error $ unlines [+ "elimUserDefined: unexpected constructor"+ , " closure: " ++ show closure+ , " expected: " ++ show expected+ , " actual: " ++ show actual+-- , "** TREE **"+-- , tree+-- , "** END OF TREE **"+ ]+ _otherwise ->+ error $ "elimUserDefined: unexpected closure: "+ ++ show closure++ goArgs :: [Some Classified] -> [Box] -> IO [Some Classified]+ goArgs acc [] = return (reverse acc)+ goArgs acc (Box b:bs) = do+ mc <- runExceptT $ classifyIO b+ case mc of+ Right c -> goArgs (Some (Classified c (unsafeCoerce b)) : acc) bs+ Left _ -> goArgs acc bs++{-------------------------------------------------------------------------------+ Show++ Showing values is mutually recursive with classification: when we show a+ value classified as @UserDefined@, we recursively classify the nested values+ /when/ we show the value.+-------------------------------------------------------------------------------}++-- | Show any value+--+-- This shows any value, as long as it's not unlifted. The result should be+-- equal to show instances, with the following caveats:+--+-- * User-defined types (types not explicitly known to this library) with a+-- /custom/ Show instance will still be showable, but the result will be+-- what the /derived/ show instance would have done.+-- * Record field names are not known at runtime, so they are not shown.+-- * UNPACKed data is not visible to this library (if you compile with @-O0@+-- @gch@ will not unpack data, so that might be a workaround if necessary).+--+-- If classification fails, we show the actual closure.+anythingToString :: forall a. a -> String+anythingToString x =+ case classified x of+ Right classifier -> showClassifiedValue 0 classifier ""+ Left closure -> show closure++deriving instance Show (Classifier a)+deriving instance Show (MaybeF Classified a)+deriving instance Show (EitherF Classified a b)+deriving instance Show (MaybePairF Classified a b)+deriving instance Show (Some Classified)++instance Show (Classified a) where+ showsPrec p (Classified c x) = showParen (p >= 11) $+ case canShowClassified c of+ Dict ->+ showString "Classified "+ . showsPrec 11 c+ . showString " "+ . showsPrec 11 x++instance SListI xs => Show (Classifiers xs) where+ show (Classifiers xs) = go (hpure Dict)+ where+ go :: NP (Dict (Compose Show Classified)) xs -> String+ go dicts =+ case all_NP dicts of+ Dict -> "(" ++ show xs ++ ")"++-- | Show the classified value (without the classifier)+showClassifiedValue :: Int -> Classified a -> ShowS+showClassifiedValue p (Classified c x) =+ case canShowClassified c of+ Dict -> showsPrec p x++canShowClassified :: Classifier a -> Dict Show a+canShowClassified = go+ where+ go :: Classifier a -> Dict Show a++ --+ -- Simple cases+ --++ -- Primitive types+ go C_Bool = Dict+ go C_Char = Dict+ go C_Double = Dict+ go C_Float = Dict+ go C_Int = Dict+ go C_Int16 = Dict+ go C_Int8 = Dict+ go C_Int32 = Dict+ go C_Int64 = Dict+ go C_Integer = Dict+ go C_Ordering = Dict+ go C_Unit = Dict+ go C_Word = Dict+ go C_Word8 = Dict+ go C_Word16 = Dict+ go C_Word32 = Dict+ go C_Word64 = Dict++ -- String types+ go C_String = Dict+ go C_BS_Strict = Dict+ go C_BS_Lazy = Dict+ go C_BS_Short = Dict+ go C_Text_Strict = Dict+ go C_Text_Lazy = Dict++ -- Aeson+ go C_Value = Dict++ -- Reference cells+ go C_STRef = Dict+ go C_TVar = Dict+ go C_MVar = Dict++ -- Functions+ go C_Fun = Dict++ -- User-defined+ go (C_Custom SConstr) = Dict++ --+ -- Compound+ --++ go (C_Maybe c) = goMaybeF c+ go (C_Either c) = goEitherF c+ go (C_List c) = goMaybeF c+ go (C_Ratio c) = goF c+ go (C_Set c) = goMaybeF c+ go (C_Map c) = goMaybePairF c+ go C_IntSet = Dict+ go (C_IntMap c) = goMaybeF c+ go (C_Sequence c) = goMaybeF c+ go (C_Tree c) = goF c++ go (C_Tuple (Classifiers cs)) =+ case all_NP (hmap (canShowClassified . classifiedType) cs) of+ Dict -> Dict++ goMaybeF :: forall f a.+ (forall x. Show x => Show (f x))+ => MaybeF Classified a -> Dict Show (f a)+ goMaybeF FNothing = Dict+ goMaybeF (FJust c) = case go (classifiedType c) of+ Dict -> Dict++ goEitherF :: forall f a b.+ (forall x y. (Show x, Show y) => Show (f x y))+ => EitherF Classified a b -> Dict Show (f a b)+ goEitherF (FLeft c) = case go (classifiedType c) of+ Dict -> Dict+ goEitherF (FRight c) = case go (classifiedType c) of+ Dict -> Dict++ goF :: forall f a.+ (forall x. Show x => Show (f x))+ => Classified a -> Dict Show (f a )+ goF c = case go (classifiedType c) of+ Dict -> Dict++ goMaybePairF :: forall f a b.+ (forall x y. (Show x, Show y) => Show (f x y))+ => MaybePairF Classified a b -> Dict Show (f a b)+ goMaybePairF FNothingPair = Dict+ goMaybePairF (FJustPair c c') = case ( go (classifiedType c)+ , go (classifiedType c')+ ) of+ (Dict, Dict) -> Dict++instance KnownConstr c => Show (UserDefined c) where+ showsPrec p x =+ case fromUserDefined x of+ [] -> showString constrName+ xs -> showParen (p >= 11)+ . (showString constrName .)+ . foldl (.) id+ . map (\(Some x') -> showString " " . showClassifiedValue 11 x')+ $ xs+ where+ Constr{constrName} = knownConstr (sing @_ @c)
+ src/Debug/RecoverRTTI/ClosureTree.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE BangPatterns #-}++module Debug.RecoverRTTI.ClosureTree (+ showClosureTree+ ) where++import Data.List+import GHC.Exts.Heap++-- | Show closure tree up to the given depth+--+-- Used only for internal debugging+showClosureTree :: Int -> a -> IO String+showClosureTree = \d -> go d 0 . asBox+ where+ go :: Int -> Int -> Box -> IO String+ go 0 _ _ = return ""+ go d i x@(Box !_) = do+ closure <- getBoxedClosureData x+ render closure <$> mapM (go (d - 1) (i + 2)) (allClosures closure)+ where+ render :: Closure -> [String] -> String+ render closure nested = intercalate "\n" $+ (replicate i ' ' ++ show closure)+ : nested
+ src/Debug/RecoverRTTI/Constr.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++{-# OPTIONS_GHC -Wno-redundant-constraints #-}++-- | Type-level metadata+module Debug.RecoverRTTI.Constr (+ Constr(..)+ , KnownConstr+ , knownConstr+ , prettyKnownConstr+ , elimKnownConstr+ -- | Compute all known constructors+ , Constrs+ , GConstrs+ , GConstrsOfType+ , ConstrOf+ , IsConstrOf(..)+ , checkIsConstrOf+ , Sing(..)+ ) where++import Data.Kind+import Data.List (intercalate)+import Data.SOP+import Data.Type.Equality+import GHC.Generics+import GHC.TypeLits++import Debug.RecoverRTTI.Util+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Type-level metadata+-------------------------------------------------------------------------------}++data Constr a = Constr {+ constrPkg :: a+ , constrModl :: a+ , constrName :: a+ }+ deriving (Show, Eq)++type family ConstrPkg (c :: Constr a) :: a where ConstrPkg ('Constr p _ _) = p+type family ConstrModl (c :: Constr a) :: a where ConstrModl ('Constr _ m _) = m+type family ConstrName (c :: Constr a) :: a where ConstrName ('Constr _ _ c) = c++class (+ KnownSymbol (ConstrPkg c)+ , KnownSymbol (ConstrModl c)+ , KnownSymbol (ConstrName c)+ , c ~ 'Constr (ConstrPkg c) (ConstrModl c) (ConstrName c)+ ) => KnownConstr c+instance (+ KnownSymbol (ConstrPkg c)+ , KnownSymbol (ConstrModl c)+ , KnownSymbol (ConstrName c)+ , c ~ 'Constr (ConstrPkg c) (ConstrModl c) (ConstrName c)+ ) => KnownConstr c++knownConstr ::+ forall c. Sing (c :: Constr Symbol) -> Constr String+knownConstr SConstr = Constr {+ constrPkg = symbolVal (Proxy @(ConstrPkg c))+ , constrModl = symbolVal (Proxy @(ConstrModl c))+ , constrName = symbolVal (Proxy @(ConstrName c))+ }++prettyKnownConstr :: Sing (c :: Constr Symbol) -> String+prettyKnownConstr s = intercalate "." [constrPkg, constrModl, constrName]+ where+ Constr{constrPkg, constrModl, constrName} = knownConstr s++elimKnownConstr :: forall r.+ Constr String+ -> (forall c. Sing (c :: Constr Symbol) -> r)+ -> r+elimKnownConstr Constr{constrPkg, constrModl, constrName} k =+ elimKnownSymbol constrPkg $ \pPkg ->+ elimKnownSymbol constrModl $ \pModl ->+ elimKnownSymbol constrName $ \pName ->+ go pPkg pModl pName+ where+ go :: forall pkg modl constr. (+ KnownSymbol pkg+ , KnownSymbol modl+ , KnownSymbol constr+ )+ => Proxy pkg -> Proxy modl -> Proxy constr -> r+ go _ _ _ = k (sing :: Sing ('Constr pkg modl constr))++{-------------------------------------------------------------------------------+ Singleton+-------------------------------------------------------------------------------}++data instance Sing (c :: Constr Symbol) where+ SConstr :: KnownConstr c => Sing c++instance KnownConstr c => SingI (c :: Constr Symbol) where+ sing = SConstr++instance Show (Sing (c :: Constr Symbol)) where+ showsPrec p proxy = showParen (p >= 11) $+ showString "SConstr "+ . showsPrec 11 (knownConstr proxy)++instance DecidableEquality (Constr Symbol) where+ decideEquality :: forall c c'.+ Sing (c :: Constr Symbol)+ -> Sing (c' :: Constr Symbol)+ -> Maybe (c :~: c')+ decideEquality SConstr SConstr =+ case ( decideEquality (sing :: Sing (ConstrPkg c)) (sing :: Sing (ConstrPkg c'))+ , decideEquality (sing :: Sing (ConstrModl c)) (sing :: Sing (ConstrModl c'))+ , decideEquality (sing :: Sing (ConstrName c)) (sing :: Sing (ConstrName c'))+ ) of+ (Just Refl, Just Refl, Just Refl) ->+ Just Refl+ _otherwise ->+ Nothing++{-------------------------------------------------------------------------------+ Reverse direction: from type to the known constructors+-------------------------------------------------------------------------------}++-- | Compute all constructors of the given type+type family Constrs (a :: Type) :: [Constr Symbol] where+ Constrs a = GConstrs (Rep a)++type family GConstrs f :: [Constr Symbol] where+ GConstrs (M1 D ('MetaData typ modl pkg isNewtype) f) =+ GConstrsOfType pkg modl f '[]++type family GConstrsOfType pkg modl f acc :: [Constr Symbol] where+ GConstrsOfType pkg modl (f :+: g) acc =+ GConstrsOfType pkg modl g (GConstrsOfType pkg modl f acc)+ GConstrsOfType pkg modl (M1 C ('MetaCons constr fixity isRecord) f) acc =+ 'Constr pkg modl constr ': acc++-- | Require that specified type has the given constructor+--+-- Intended usage:+--+-- > castUserDefined :: forall c a. ConstrOf a c => UserDefined c -> a+-- > castUserDefined = unsafeCoerce+type family ConstrOf (a :: Type) (c :: Constr Symbol) :: Constraint where+ ConstrOf a c =+ Assert+ (Elem c (Constrs a))+ (TypeError (+ ( 'ShowType c+ ':<>: 'Text " is not a valid constructor of "+ ':<>: 'ShowType a+ )+ ':$$: ( 'Text "Valid constructors are: "+ ':<>: 'ShowType (Constrs a)+ )+ ))++data IsConstrOf (a :: Type) (c :: Constr Symbol) where+ IsConstrOf :: Elem c (Constrs a) ~ 'True => IsConstrOf a c++checkIsConstrOf :: forall (a :: Type) (c :: Constr Symbol).+ SingI (Constrs a)+ => Sing c -> Maybe (IsConstrOf a c)+checkIsConstrOf s =+ aux <$> checkIsElem s (sing @_ @(Constrs a))+ where+ aux :: IsElem c (Constrs a) -> IsConstrOf a c+ aux IsElem = IsConstrOf
+ src/Debug/RecoverRTTI/FlatClosure.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE RecordWildCards #-}++module Debug.RecoverRTTI.FlatClosure (+ FlatClosure(..)+ , getBoxedClosureData+ -- * Re-exports+ , Box(..)+ , asBox+ ) where++import Control.Exception (evaluate)+import Control.Monad+import GHC.Exts.Heap (Box(..), asBox)+import qualified GHC.Exts.Heap as H++-- | Flattened form of 'Closure' (with indirection nodes removed)+--+-- We only include the fields of 'Closure' that we are interested in.+--+-- TODO: For functions ('FunClosure', 'PAPClosure') we don't currently include+-- any information at all. We could potentially do better here.+data FlatClosure =+ -- | Constructor application+ ConstrClosure {+ ptrArgs :: [Box]+ , pkg :: String+ , modl :: String+ , name :: String+ }++ -- | Functions+ --+ -- We map 'H.FunClosure', 'H.PAPClosure' and H.BCOClosure' all to this.+ | FunClosure++ -- | Unrecognized closure type+ | OtherClosure H.Closure+ deriving (Show)++getBoxedClosureData :: Box -> IO FlatClosure+getBoxedClosureData b = do+ tryForceBox b+ fromClosure =<< H.getBoxedClosureData b+ where+ fromClosure :: H.Closure -> IO FlatClosure+ fromClosure = \case+ -- Indirections+ --+ -- For background on black holes, see "Implementing Lazy Functional+ -- Languages on Stock Hardware: The Spineless Tagless G-machine", Simon+ -- Peyton Jones, Journal of Functional Programming, July 1992, section+ -- 9.3.3 "Black holes".++ H.BlackholeClosure _ x' -> getBoxedClosureData x'+ H.IndClosure _ x' -> getBoxedClosureData x'++ -- Constructor application++ H.ConstrClosure{ptrArgs, pkg, modl, name} ->+ return $ ConstrClosure{..}++ -- Functions++ H.FunClosure{} -> return $ FunClosure+ H.PAPClosure{} -> return $ FunClosure+ H.BCOClosure{} -> return $ FunClosure++ -- Other kinds of constructors++ otherClosure ->+ return $ OtherClosure otherClosure++-- | Force the value to WHNF, if possible+--+-- We /cannot/ force the argument until we know what kind of closure we're+-- dealing with. If this is an unlifted closure, forcing it will result in a+-- ghc runtime crash.+tryForceBox :: Box -> IO ()+tryForceBox b@(Box x) = do+ closure <- H.getBoxedClosureData b+ case closure of++ H.APClosure{} -> void $ evaluate x+ H.ThunkClosure{} -> void $ evaluate x+ H.SelectorClosure{} -> void $ evaluate x+ _otherwise -> return ()
+ src/Debug/RecoverRTTI/Modules.hs view
@@ -0,0 +1,191 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE TypeFamilies #-}++-- | Modules we recognize types from+module Debug.RecoverRTTI.Modules (+ KnownPkg(..)+ , KnownModule(..)+ , Sing(..)+ -- * Matching+ , inKnownModule+ , inKnownModuleNested+ ) where++import Control.Monad+import Data.List (isPrefixOf)++import Debug.RecoverRTTI.FlatClosure+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Packages+-------------------------------------------------------------------------------}++data KnownPkg =+ PkgGhcPrim+ | PkgBase+ | PkgByteString+ | PkgText+ | PkgIntegerWiredIn+ | PkgGhcBignum+ | PkgContainers+ | PkgAeson++data family KnownModule (pkg :: KnownPkg)++{-------------------------------------------------------------------------------+ Singleton instance for KnownPkg+-------------------------------------------------------------------------------}++data instance Sing (pkg :: KnownPkg) where+ SGhcPrim :: Sing 'PkgGhcPrim+ SBase :: Sing 'PkgBase+ SByteString :: Sing 'PkgByteString+ SText :: Sing 'PkgText+ SIntegerWiredIn :: Sing 'PkgIntegerWiredIn+ SGhcBignum :: Sing 'PkgGhcBignum+ SContainers :: Sing 'PkgContainers+ SAeson :: Sing 'PkgAeson++instance SingI 'PkgGhcPrim where sing = SGhcPrim+instance SingI 'PkgBase where sing = SBase+instance SingI 'PkgByteString where sing = SByteString+instance SingI 'PkgText where sing = SText+instance SingI 'PkgIntegerWiredIn where sing = SIntegerWiredIn+instance SingI 'PkgGhcBignum where sing = SGhcBignum+instance SingI 'PkgContainers where sing = SContainers+instance SingI 'PkgAeson where sing = SAeson++{-------------------------------------------------------------------------------+ Modules in @ghc-pri@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgGhcPrim =+ GhcTypes+ | GhcTuple++{-------------------------------------------------------------------------------+ Modules in @base@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgBase =+ GhcInt+ | GhcWord+ | GhcSTRef+ | GhcMVar+ | GhcConcSync+ | GhcMaybe+ | GhcReal+ | DataEither++{-------------------------------------------------------------------------------+ Modules in @bytestring@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgByteString =+ DataByteStringInternal+ | DataByteStringLazyInternal+ | DataByteStringShortInternal++{-------------------------------------------------------------------------------+ Modules in @text@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgText =+ DataTextInternal+ | DataTextInternalLazy++{-------------------------------------------------------------------------------+ Modules in @integer-wired-in@ (this is a virtual package)+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgIntegerWiredIn =+ GhcIntegerType++{-------------------------------------------------------------------------------+ Modules in @ghc-bignum@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgGhcBignum =+ GhcNumInteger++{-------------------------------------------------------------------------------+ Modules in @containers@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgContainers =+ DataSetInternal+ | DataMapInternal+ | DataIntSetInternal+ | DataIntMapInternal+ | DataSequenceInternal+ | DataTree++{-------------------------------------------------------------------------------+ Modules in @aeson@+-------------------------------------------------------------------------------}++data instance KnownModule 'PkgAeson =+ DataAesonTypesInternal++{-------------------------------------------------------------------------------+ Matching+-------------------------------------------------------------------------------}++-- | Check if the given closure is from a known package/module+inKnownModule :: SingI pkg+ => KnownModule pkg+ -> FlatClosure -> Maybe String+inKnownModule modl = fmap fst . inKnownModuleNested modl++-- | Generalization of 'inKnownModule' that additionally returns nested pointers+inKnownModuleNested :: SingI pkg+ => KnownModule pkg+ -> FlatClosure -> Maybe (String, [Box])+inKnownModuleNested = go sing+ where+ go :: Sing pkg -> KnownModule pkg -> FlatClosure -> Maybe (String, [Box])+ go knownPkg knownModl ConstrClosure{pkg, modl, name, ptrArgs} = do+ guard (namePkg knownPkg `isPrefixOf` pkg) -- ignore the version number+ guard (modl == nameModl knownPkg knownModl)+ return (name, ptrArgs)+ go _ _ _otherClosure = Nothing++ namePkg :: Sing (pkg :: KnownPkg) -> String+ namePkg SGhcPrim = "ghc-prim"+ namePkg SBase = "base"+ namePkg SByteString = "bytestring"+ namePkg SText = "text"+ namePkg SIntegerWiredIn = "integer-wired-in"+ namePkg SGhcBignum = "ghc-bignum"+ namePkg SContainers = "containers"+ namePkg SAeson = "aeson"++ nameModl :: Sing (pkg :: KnownPkg) -> KnownModule pkg -> String+ nameModl SGhcPrim GhcTypes = "GHC.Types"+ nameModl SGhcPrim GhcTuple = "GHC.Tuple"+ nameModl SBase GhcInt = "GHC.Int"+ nameModl SBase GhcWord = "GHC.Word"+ nameModl SBase GhcSTRef = "GHC.STRef"+ nameModl SBase GhcMVar = "GHC.MVar"+ nameModl SBase GhcConcSync = "GHC.Conc.Sync"+ nameModl SBase GhcMaybe = "GHC.Maybe"+ nameModl SBase GhcReal = "GHC.Real"+ nameModl SBase DataEither = "Data.Either"+ nameModl SByteString DataByteStringInternal = "Data.ByteString.Internal"+ nameModl SByteString DataByteStringLazyInternal = "Data.ByteString.Lazy.Internal"+ nameModl SByteString DataByteStringShortInternal = "Data.ByteString.Short.Internal"+ nameModl SText DataTextInternal = "Data.Text.Internal"+ nameModl SText DataTextInternalLazy = "Data.Text.Internal.Lazy"+ nameModl SIntegerWiredIn GhcIntegerType = "GHC.Integer.Type"+ nameModl SGhcBignum GhcNumInteger = "GHC.Num.Integer"+ nameModl SContainers DataSetInternal = "Data.Set.Internal"+ nameModl SContainers DataMapInternal = "Data.Map.Internal"+ nameModl SContainers DataIntSetInternal = "Data.IntSet.Internal"+ nameModl SContainers DataIntMapInternal = "Data.IntMap.Internal"+ nameModl SContainers DataSequenceInternal = "Data.Sequence.Internal"+ nameModl SContainers DataTree = "Data.Tree"+ nameModl SAeson DataAesonTypesInternal = "Data.Aeson.Types.Internal"
+ src/Debug/RecoverRTTI/Tuple.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}++module Debug.RecoverRTTI.Tuple (+ -- * Wrapped tuple+ WrappedTuple(WrappedTuple, TNil, TCons)+ -- * Auxiliary+ , bimapTuple+ -- * Conversion between tuples and NP+ , tupleFromNP+ , tupleToNP+ -- * Re-exports+ , module Debug.RecoverRTTI.Tuple.Recursive+ , module Debug.RecoverRTTI.Tuple.Size+ ) where++import Data.SOP hiding (NS(..))++import Debug.RecoverRTTI.Tuple.Recursive+import Debug.RecoverRTTI.Tuple.Size+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Wrapped tuple++ NOTE: We cannot add any dictionaries in @WrappedTuple@ itself, it /MUST/ be+ a type synonym: it is critical that we can 'unsafeCoerce' a regular tuple to a+ wrapped tuple.+-------------------------------------------------------------------------------}++newtype WrappedTuple xs = WrappedTuple (Tuple xs)++pattern TNil ::+ forall xs. (SListI xs, IsValidSize (Length xs))+ => xs ~ '[]+ => WrappedTuple xs+pattern TNil <- (viewWrapped -> TupleEmpty)+ where+ TNil = WrappedTuple ()++pattern TCons ::+ forall xs'. (SListI xs', IsValidSize (Length xs'))+ => forall x xs . (xs' ~ (x ': xs), SListI xs, IsValidSize (Length xs))+ => x -> WrappedTuple xs -> WrappedTuple xs'+pattern TCons x xs <- (viewWrapped -> TupleNonEmpty x xs)+ where+ TCons x xs = consWrapped (x, xs)++{-# COMPLETE TNil, TCons #-}++{-------------------------------------------------------------------------------+ Auxiliary+-------------------------------------------------------------------------------}++bimapTuple ::+ ( SListI xs+ , SListI ys+ , IsValidSize (Length (x ': xs))+ , Length xs ~ Length ys+ )+ => (x -> y)+ -> (WrappedTuple xs -> WrappedTuple ys)+ -> WrappedTuple (x ': xs) -> WrappedTuple (y ': ys)+bimapTuple f g (TCons x xs) = TCons (f x) (g xs)++{-------------------------------------------------------------------------------+ Conversion to/from NP+-------------------------------------------------------------------------------}++tupleFromNP :: forall xs.+ (SListI xs, IsValidSize (Length xs))+ => NP I xs -> WrappedTuple xs+tupleFromNP Nil = TNil+tupleFromNP (I x :* xs) = smallerIsValid (Proxy @(Length xs))+ $ TCons x (tupleFromNP xs)++tupleToNP ::+ (SListI xs, IsValidSize (Length xs))+ => WrappedTuple xs -> NP I xs+tupleToNP TNil = Nil+tupleToNP (TCons x xs) = I x :* tupleToNP xs++{-------------------------------------------------------------------------------+ Internal auxiliary functions for defining the pattern synonym+-------------------------------------------------------------------------------}++data TupleView xs where+ TupleEmpty :: TupleView '[]+ TupleNonEmpty :: (SListI xs, IsValidSize (Length xs))+ => x -> WrappedTuple xs -> TupleView (x ': xs)++viewWrapped ::+ (SListI xs, IsValidSize (Length xs))+ => WrappedTuple xs+ -> TupleView xs+viewWrapped (WrappedTuple t) =+ go sList t+ where+ go :: forall xs.+ IsValidSize (Length xs)+ => SList xs -> Tuple xs -> TupleView xs+ go SNil () = TupleEmpty+ go SCons xs = goCons xs++ goCons :: forall x xs.+ (SListI xs, IsValidSize (Length (x ': xs)))+ => Tuple (x ': xs) -> TupleView (x ': xs)+ goCons xs =+ smallerIsValid (Proxy @(Length (x ': xs))) $+ TupleNonEmpty x (WrappedTuple xs')+ where+ (x, xs') = uncons (Proxy @xs) isValidSize xs++consWrapped :: forall x xs.+ (SListI xs, IsValidSize (Length (x ': xs)))+ => (x, WrappedTuple xs) -> WrappedTuple (x ': xs)+consWrapped (x, WrappedTuple xs) =+ WrappedTuple (cons (Proxy @xs) isValidSize (x, xs))++{-------------------------------------------------------------------------------+ Instances+-------------------------------------------------------------------------------}++instance ( SListI xs+ , IsValidSize (Length xs)+ , All Show xs+ ) => Show (WrappedTuple xs) where+ showsPrec _ =+ show_tuple+ . hcollapse+ . hcmap (Proxy @Show) (mapIK shows)+ . tupleToNP+ where+ -- Copied from @GHC.Show@ (not exported)+ show_tuple :: [ShowS] -> ShowS+ show_tuple ss = showChar '('+ . foldr1 (\s r -> s . showChar ',' . r) ss+ . showChar ')'++instance ( SListI xs+ , IsValidSize (Length xs)+ , All Eq xs+ ) => Eq (WrappedTuple xs) where+ (tupleToNP -> xs) == (tupleToNP -> ys) =+ and . hcollapse $ hczipWith (Proxy @Eq) (mapIIK (==)) xs ys
+ src/Debug/RecoverRTTI/Tuple/Recursive.hs view
@@ -0,0 +1,429 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+-- {-# LANGUAGE UndecidableSuperClasses #-}++-- Disable the GHC pattern match checker (this makes compilation /much/ faster)+--+-- Verified that this module compiles without warnings for smaller maximum+-- tuple size.+--+-- For some details, see+--+-- * https://gitlab.haskell.org/ghc/ghc/-/issues/17836+-- * https://gitlab.haskell.org/ghc/ghc/-/issues/16382+{-# OPTIONS_GHC -Wno-overlapping-patterns -Wno-incomplete-patterns -Wno-incomplete-uni-patterns -fno-opt-coercion #-}++-- | Provide a recursive views on tuples+module Debug.RecoverRTTI.Tuple.Recursive (+ Tuple+ , cons+ , uncons+ ) where++import Data.SOP++import Debug.RecoverRTTI.Tuple.Size+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Generated+-------------------------------------------------------------------------------}++type family Tuple xs where+ Tuple '[] =+ {- 00 -} ()+ Tuple '[x1] =+ {- 01 -} (x1)+ Tuple '[x1, x2] =+ {- 02 -} (x1, x2)+ Tuple '[x1, x2, x3] =+ {- 03 -} (x1, x2, x3)+ Tuple '[x1, x2, x3, x4] =+ {- 04 -} (x1, x2, x3, x4)+ Tuple '[x1, x2, x3, x4, x5] =+ {- 05 -} (x1, x2, x3, x4, x5)+ Tuple '[x1, x2, x3, x4, x5, x6] =+ {- 06 -} (x1, x2, x3, x4, x5, x6)+ Tuple '[x1, x2, x3, x4, x5, x6, x7] =+ {- 07 -} (x1, x2, x3, x4, x5, x6, x7)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8] =+ {- 08 -} (x1, x2, x3, x4, x5, x6, x7, x8)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9] =+ {- 09 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10] =+ {- 10 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11] =+ {- 11 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12] =+ {- 12 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13] =+ {- 13 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14] =+ {- 14 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15] =+ {- 15 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16] =+ {- 16 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17] =+ {- 17 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18] =+ {- 18 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19] =+ {- 19 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20] =+ {- 20 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21] =+ {- 21 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22] =+ {- 22 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23] =+ {- 23 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24] =+ {- 24 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25] =+ {- 25 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26] =+ {- 26 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27] =+ {- 27 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28] =+ {- 28 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29] =+ {- 29 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30] =+ {- 30 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31] =+ {- 31 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32] =+ {- 32 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33] =+ {- 33 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34] =+ {- 34 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35] =+ {- 35 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36] =+ {- 36 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37] =+ {- 37 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38] =+ {- 38 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39] =+ {- 39 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40] =+ {- 40 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41] =+ {- 41 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42] =+ {- 42 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43] =+ {- 43 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44] =+ {- 44 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45] =+ {- 45 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46] =+ {- 46 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47] =+ {- 47 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48] =+ {- 48 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49] =+ {- 49 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50] =+ {- 50 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51] =+ {- 51 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52] =+ {- 52 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53] =+ {- 53 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54] =+ {- 54 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55] =+ {- 55 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56] =+ {- 56 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57] =+ {- 57 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58] =+ {- 58 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59] =+ {- 59 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60] =+ {- 60 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61] =+ {- 61 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61)+ Tuple '[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62] =+ {- 62 -} (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62)++cons :: forall x xs. SListI xs+ => Proxy xs+ -> ValidSize (Length (x ': xs))+ -> (x, Tuple xs) -> Tuple (x ': xs)+cons _ (ValidSize _n notTooBig) = go shape+ where+ go :: Shape xs -> (x, Tuple xs) -> Tuple (x ': xs)+ go ShapeNil (x1, ()) =+ (x1)+ go (ShapeCons ShapeNil) (x1, (x2)) =+ (x1, x2)+ go (ShapeCons (ShapeCons ShapeNil)) (x1, (x2, x3)) =+ (x1, x2, x3)+ go (ShapeCons (ShapeCons (ShapeCons ShapeNil))) (x1, (x2, x3, x4)) =+ (x1, x2, x3, x4)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))) (x1, (x2, x3, x4, x5)) =+ (x1, x2, x3, x4, x5)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))) (x1, (x2, x3, x4, x5, x6)) =+ (x1, x2, x3, x4, x5, x6)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))) (x1, (x2, x3, x4, x5, x6, x7)) =+ (x1, x2, x3, x4, x5, x6, x7)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))) (x1, (x2, x3, x4, x5, x6, x7, x8)) =+ (x1, x2, x3, x4, x5, x6, x7, x8)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62)) =+ (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62)+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons _)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) _ =+ notTooBig (TooBig :: TooBig (Length (x ': xs)))++uncons :: forall x xs. SListI xs+ => Proxy xs+ -> ValidSize (Length (x ': xs))+ -> Tuple (x ': xs) -> (x, Tuple xs)+uncons _ (ValidSize _n notTooBig) = go shape+ where+ go :: Shape xs -> Tuple (x ': xs) -> (x, Tuple xs)+ go ShapeNil (x1) =+ (x1, ())+ go (ShapeCons ShapeNil) (x1, x2) =+ (x1, (x2))+ go (ShapeCons (ShapeCons ShapeNil)) (x1, x2, x3) =+ (x1, (x2, x3))+ go (ShapeCons (ShapeCons (ShapeCons ShapeNil))) (x1, x2, x3, x4) =+ (x1, (x2, x3, x4))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))) (x1, x2, x3, x4, x5) =+ (x1, (x2, x3, x4, x5))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))) (x1, x2, x3, x4, x5, x6) =+ (x1, (x2, x3, x4, x5, x6))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))) (x1, x2, x3, x4, x5, x6, x7) =+ (x1, (x2, x3, x4, x5, x6, x7))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))) (x1, x2, x3, x4, x5, x6, x7, x8) =+ (x1, (x2, x3, x4, x5, x6, x7, x8))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons ShapeNil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) (x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62) =+ (x1, (x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31, x32, x33, x34, x35, x36, x37, x38, x39, x40, x41, x42, x43, x44, x45, x46, x47, x48, x49, x50, x51, x52, x53, x54, x55, x56, x57, x58, x59, x60, x61, x62))+ go (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons (ShapeCons _)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) _ =+ notTooBig (TooBig :: TooBig (Length (x ': xs)))
+ src/Debug/RecoverRTTI/Tuple/Size.hs view
@@ -0,0 +1,517 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++{-# OPTIONS_GHC -Wno-overlapping-patterns -Wno-incomplete-patterns -Wno-incomplete-uni-patterns -fno-opt-coercion #-}++-- | Valid tuple size+module Debug.RecoverRTTI.Tuple.Size (+ ValidSize(..)+ , TooBig(..)+ , smallerIsValid+ , IsValidSize(..)+ , liftValidSize+ , toValidSize+ ) where++import Data.Proxy+import Data.SOP.Dict++import Debug.RecoverRTTI.Util+import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Not generated+-------------------------------------------------------------------------------}++data ValidSize (n :: Nat) where+ ValidSize :: Sing n -> (forall r. TooBig n -> r) -> ValidSize n++smallerIsValid' :: forall n. ValidSize ('S n) -> ValidSize n+smallerIsValid' = \(ValidSize (SS n) tooBig) -> ValidSize n $ aux tooBig+ where+ aux :: (TooBig ('S n) -> r) -> TooBig n -> r+ aux tooBig TooBig = tooBig (TooBig :: TooBig ('S n))++smallerIsValid :: forall n r.+ IsValidSize ('S n)+ => Proxy ('S n)+ -> (IsValidSize n => r)+ -> r+smallerIsValid _ k =+ case liftValidSize (smallerIsValid' valid) of+ Dict -> k+ where+ valid :: ValidSize ('S n)+ valid = isValidSize++class SingI n => IsValidSize n where+ isValidSize :: ValidSize n++{-------------------------------------------------------------------------------+ Generated+-------------------------------------------------------------------------------}++data TooBig (n :: Nat) where+ TooBig :: TooBig ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S n)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))++liftValidSize :: forall n. ValidSize n -> Dict IsValidSize n+liftValidSize (ValidSize n notTooBig) = go n+ where+ go :: Sing n -> Dict IsValidSize n+ go SZ =+ Dict+ go (SS SZ) =+ Dict+ go (SS (SS SZ)) =+ Dict+ go (SS (SS (SS SZ))) =+ Dict+ go (SS (SS (SS (SS SZ)))) =+ Dict+ go (SS (SS (SS (SS (SS SZ))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS SZ)))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS SZ))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS SZ)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ Dict+ go (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS (SS _))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) =+ notTooBig (TooBig :: TooBig n)++instance IsValidSize 'Z where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S 'Z) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S 'Z)) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S 'Z))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S 'Z)))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S 'Z))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S 'Z)))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S 'Z))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++instance IsValidSize ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) where+ isValidSize = ValidSize sing $ \case++toValidSize :: Int -> Maybe (Some ValidSize)+toValidSize = go+ where+ go :: Int -> Maybe (Some ValidSize)+ go 0 = Just . Some $+ isValidSize @'Z+ go 1 = Just . Some $+ isValidSize @('S 'Z)+ go 2 = Just . Some $+ isValidSize @('S ('S 'Z))+ go 3 = Just . Some $+ isValidSize @('S ('S ('S 'Z)))+ go 4 = Just . Some $+ isValidSize @('S ('S ('S ('S 'Z))))+ go 5 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S 'Z)))))+ go 6 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S 'Z))))))+ go 7 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S 'Z)))))))+ go 8 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))+ go 9 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))+ go 10 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))+ go 11 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))+ go 12 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))+ go 13 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))+ go 14 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))+ go 15 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))+ go 16 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))+ go 17 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))+ go 18 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))+ go 19 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))+ go 20 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))+ go 21 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))+ go 22 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))+ go 23 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))+ go 24 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))+ go 25 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))+ go 26 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))+ go 27 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))+ go 28 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))+ go 29 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))+ go 30 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))+ go 31 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))+ go 32 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))+ go 33 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))+ go 34 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))+ go 35 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))+ go 36 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))+ go 37 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))+ go 38 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))+ go 39 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))+ go 40 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))+ go 41 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))+ go 42 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))+ go 43 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))+ go 44 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))+ go 45 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))+ go 46 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))+ go 47 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))+ go 48 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))+ go 49 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))+ go 50 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))+ go 51 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))+ go 52 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 53 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 54 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 55 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 56 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 57 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 58 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 59 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 60 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 61 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go 62 = Just . Some $+ isValidSize @('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S ('S 'Z))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))+ go _ = Nothing
+ src/Debug/RecoverRTTI/UserDefined.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- | User-defined types+--+-- For user-defined types, we have no way of actually inferring the /type/ at+-- runtime. Instead, we merely reflect (at the type level) which /constructor/+-- was used to construct the value. This gives the library sufficient context+-- to /show/ values, and it gives client code that /is/ aware of these custom+-- types sufficient context to recover the full type information, if desired.+-- See "Test.RecoverRTTI.Staged" for an example of the latter.+module Debug.RecoverRTTI.UserDefined (+ -- | Type inferred for user-defined types+ UserDefined(..)+ , unsafeCoerceUserDefined+ ) where++import Data.Proxy+import GHC.TypeLits+import GHC.Exts+import Unsafe.Coerce (unsafeCoerce)++import Debug.RecoverRTTI.Constr+import Debug.RecoverRTTI.Util++{-------------------------------------------------------------------------------+ User-defined types+-------------------------------------------------------------------------------}++-- | User-defined type+--+-- For user-defined types we recover, at the type level, information about the+-- constructor. In /principle/ of course this means that this tells us what+-- the type of this thing is; if+--+-- > data MyType .. = MyConstr .. | ...+--+-- then @coerce :: UserDefined "MyConstr" -> MyType@ should be safe.+--+-- We defer classification of the /arguments/ to the constructor. This is+-- necessary, because if we tried to do this eagerly---recording those types as+-- part of the 'UserDefined' type---we might end up "unwinding" recursive types+-- at the type level; for example, something like+--+-- > data MyList = MyNil | MyCons a (MyList a)+--+-- could then result in something like+--+-- > UserDefined "MyCons" '[ Int, UserDefined "MyCons" '[ Int , ... ] .. ]+--+-- Detecting recursion is undecidable (that's why Haskell uses isorecursive+-- rather than equirecursive types), so instead we defer.+newtype UserDefined (c :: Constr Symbol) = UserDefined Any++-- | Safer wrapper around 'unsafeCoerce'+--+-- This is safer than 'unsafeCoerce', because we require (at the type level)+-- that the value was constructed with a constructor of the target type. This+-- means that 'unsafeCoerceUserDefined' is in fact /safe/ for types without+-- type parameters; however, for a type such as+--+-- > data MyType a = MkMyType a+--+-- 'unsafeCoerceUserDefined' can still be used to cast, say, @MyType Int@ to+-- @MyType Bool@, and so this is still unsafe.+unsafeCoerceUserDefined :: forall a c. ConstrOf a c => UserDefined c -> a+unsafeCoerceUserDefined = unsafeCoerce+ where+ _ = keepRedundantConstraint (Proxy @(ConstrOf a c))
+ src/Debug/RecoverRTTI/Util.hs view
@@ -0,0 +1,111 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-# OPTIONS_GHC -Wno-redundant-constraints #-}++module Debug.RecoverRTTI.Util (+ -- * Existentials+ Some(..)+ , elimKnownSymbol+ -- * Constraints+ , keepRedundantConstraint+ -- * Traversable+ , checkEmptyTraversable+ -- * Lists+ , dropEnds+ -- * SOP+ , VerifiedSize(..)+ , verifySize+ ) where++import Data.Kind+import Data.Proxy+import Data.SOP+import Data.Void+import GHC.TypeLits (KnownSymbol, SomeSymbol(..), someSymbolVal)++import Debug.RecoverRTTI.Util.TypeLevel++{-------------------------------------------------------------------------------+ Existentials+-------------------------------------------------------------------------------}++data Some (f :: k -> Type) where+ Some :: forall f a. f a -> Some f++elimKnownSymbol :: String -> (forall n. KnownSymbol n => Proxy n -> r) -> r+elimKnownSymbol s k =+ case someSymbolVal s of+ SomeSymbol p -> k p++{-------------------------------------------------------------------------------+ Constraints+-------------------------------------------------------------------------------}++-- | Can be used to silence individual "redundant constraint" warnings+--+-- > foo :: ConstraintUsefulForDebugging => ...+-- > foo =+-- > ..+-- > where+-- > _ = keepRedundantConstraint (Proxy @ConstraintUsefulForDebugging))+keepRedundantConstraint :: c => proxy c -> ()+keepRedundantConstraint _ = ()++{-------------------------------------------------------------------------------+ Traversable+-------------------------------------------------------------------------------}++-- | Check if a traversable data structure is empty+--+-- Returns evidence: an element of the data-structure if it's non-empty,+-- or evidence that it is empty otherwise.+checkEmptyTraversable :: Traversable t => t a -> Either a (t Void)+checkEmptyTraversable = traverse Left++{-------------------------------------------------------------------------------+ Lists+-------------------------------------------------------------------------------}++-- | Drop the ends of a list+--+-- > dropEnds "abcde" == Just ('a',"bcd",'e')+dropEnds :: forall a. [a] -> Maybe (a, [a], a)+dropEnds = \case+ [] -> Nothing+ (a:xs) -> go a xs+ where+ go :: a -> [a] -> Maybe (a, [a], a)+ go a = goRest []+ where+ goRest :: [a] -> [a] -> Maybe (a, [a], a)+ goRest _ [] = Nothing+ goRest acc [z] = Just (a, reverse acc, z)+ goRest acc (x:xs) = goRest (x:acc) xs++{-------------------------------------------------------------------------------+ SOP+-------------------------------------------------------------------------------}++data VerifiedSize (n :: Nat) (a :: Type) where+ -- This is intentionally not kind polymorphic+ VerifiedSize :: forall n a (xs :: [Type]).+ (SListI xs, Length xs ~ n)+ => NP (K a) xs -> VerifiedSize n a++verifySize :: Sing n -> [a] -> Maybe (VerifiedSize n a)+verifySize = go+ where+ go :: Sing n -> [a] -> Maybe (VerifiedSize n a)+ go SZ [] = Just (VerifiedSize Nil)+ go (SS n) (x:xs) = do VerifiedSize np <- go n xs+ return $ VerifiedSize (K x :* np)+ go SZ (_:_) = Nothing+ go (SS _) [] = Nothing
+ src/Debug/RecoverRTTI/Util/TypeLevel.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE PolyKinds #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++module Debug.RecoverRTTI.Util.TypeLevel (+ -- * Singletons+ Sing(..)+ , SingI(..)+ , DecidableEquality(..)+ -- ** Natural numbers+ , Nat(..)+ , knownNat+ , Length+ -- * General purpose type level functions+ , Or+ , Equal+ , Elem+ , Assert+ -- * Type-level membership check+ , IsElem(..)+ , checkIsElem+ -- * Phantom type parameters+ , Phantom(..)+ , Poly(..)+ , maybePoly+ ) where++import Data.Kind+import Data.Proxy+import Data.Type.Equality+import GHC.TypeLits (ErrorMessage, Symbol, KnownSymbol, TypeError, sameSymbol)++{-------------------------------------------------------------------------------+ Singletons+-------------------------------------------------------------------------------}++data family Sing :: k -> Type++class SingI (a :: k) where+ sing :: Sing a++class DecidableEquality k where+ decideEquality :: Sing (a :: k) -> Sing (b :: k) -> Maybe (a :~: b)++{-------------------------------------------------------------------------------+ For kind 'Type', Sing is just a proxy+-------------------------------------------------------------------------------}++data instance Sing (a :: Type) where+ SProxy :: Sing (a :: Type)++instance SingI (a :: Type) where+ sing = SProxy++{-------------------------------------------------------------------------------+ Natural numbers++ Unlike @ghc@'s, these are inductively defined.+-------------------------------------------------------------------------------}++data Nat = Z | S Nat++data instance Sing (n :: Nat) where+ SZ :: Sing 'Z+ SS :: Sing n -> Sing ('S n)++instance SingI 'Z where sing = SZ+instance SingI n => SingI ('S n) where sing = SS sing++knownNat :: Sing (n :: Nat) -> Int+knownNat SZ = 0+knownNat (SS n) = knownNat n + 1++type family Length (xs :: [k]) :: Nat where+ Length '[] = 'Z+ Length (_ ': xs) = 'S (Length xs)++{-------------------------------------------------------------------------------+ Singleton instance for type-level symbols+-------------------------------------------------------------------------------}++data instance Sing (n :: Symbol) where+ SSymbol :: KnownSymbol n => Sing n++instance KnownSymbol n => SingI (n :: Symbol) where+ sing = SSymbol++instance DecidableEquality Symbol where+ decideEquality SSymbol SSymbol = sameSymbol Proxy Proxy++{-------------------------------------------------------------------------------+ Singleton instance for lists+-------------------------------------------------------------------------------}++data instance Sing (xs :: [k]) where+ SN :: Sing '[]+ SC :: Sing x -> Sing xs -> Sing (x ': xs)++instance SingI '[] where sing = SN+instance (SingI x, SingI xs) => SingI (x ': xs) where sing = SC sing sing++{-------------------------------------------------------------------------------+ General purpose type level functions+-------------------------------------------------------------------------------}++type family Or (a :: Bool) (b :: Bool) where+ Or 'True b = 'True+ Or a 'True = 'True+ Or _ _ = 'False++type family Equal (x :: k) (y :: k) where+ Equal x x = 'True+ Equal x y = 'False++type family Elem (x :: k) (xs :: [k]) where+ Elem x '[] = 'False+ Elem x (y ': ys) = Or (Equal x y) (Elem x ys)++-- | Assert type-level predicate+--+-- We cannot define this in terms of a more general @If@ construct, because+-- @ghc@'s type-level language has an undefined reduction order and so we get+-- no short-circuiting.+type family Assert (b :: Bool) (err :: ErrorMessage) :: Constraint where+ Assert 'True err = ()+ Assert 'False err = TypeError err++{-------------------------------------------------------------------------------+ Decidable equality gives a decidable membership check+-------------------------------------------------------------------------------}++data IsElem (x :: k) (xs :: [k]) where+ IsElem :: Elem x xs ~ 'True => IsElem x xs++shiftIsElem :: IsElem x ys -> IsElem x (y ': ys)+shiftIsElem IsElem = IsElem++checkIsElem ::+ DecidableEquality k+ => Sing (x :: k) -> Sing (xs :: [k]) -> Maybe (IsElem x xs)+checkIsElem _ SN = Nothing+checkIsElem x (SC y ys) = case decideEquality x y of+ Just Refl -> Just IsElem+ Nothing -> shiftIsElem <$> checkIsElem x ys++{-------------------------------------------------------------------------------+ Phantom type parameters+-------------------------------------------------------------------------------}++-- | Functors with phantom arguments+class Phantom (f :: k -> Type) where+ -- | Similar to 'Data.Functor.Contravariant.phantom', but without requiring+ -- 'Functor' or 'Contravariant'+ phantom :: forall a b. f a -> f b++data Poly (f :: k -> Type) = Poly (forall (a :: k). f a)++-- | Commute @Maybe@ and @forall@+maybePoly :: Phantom f => Maybe (f a) -> Maybe (Poly f)+maybePoly = fmap (\v -> Poly (phantom v))
+ src/Debug/RecoverRTTI/Wrappers.hs view
@@ -0,0 +1,70 @@+-- | Newtype wrappers+--+-- For some types, we infer a "wrapped type" instead. It is important that+-- these wrappers are all /newtypes/ and not /datatypes, because when we have+-- a value @x :: a@ and a corresponding classifier @Classifier a@, we should be+-- able to @unsafeCoerce x@ to whatever type the classifier tells us. If we+-- don't use newtypes but datatypes here, then that would not be possible.+--+-- We use these newtypes primarily so that we can give some custom type class+-- instances. In particular, this means that for example our inferred functions+-- have a show instance, even if they are simply shown as @<Fun>@; this is+-- nonetheless stil useful, as it means that we can show /everything/, which is+-- kind of the point.+module Debug.RecoverRTTI.Wrappers (+ -- * Functions+ SomeFun(..)+ -- * Reference cells+ , SomeSTRef(..)+ , SomeMVar(..)+ , SomeTVar(..)+ ) where++import Control.Concurrent.MVar (MVar)+import Control.Concurrent.STM (TVar)+import Data.STRef (STRef)+import GHC.Exts++{-------------------------------------------------------------------------------+ Functions+-------------------------------------------------------------------------------}++-- | Functions+--+-- We do not try to infer the domain or codomain of the function.+newtype SomeFun = SomeFun (Any -> Any)++{-------------------------------------------------------------------------------+ Reference cells++ We do not try to look inside these variables to figure out the type of their+ elements; the show instance merely shows an address.+-------------------------------------------------------------------------------}++newtype SomeSTRef = SomeSTRef (STRef Any Any)+ deriving (Eq)++newtype SomeMVar = SomeMVar (MVar Any)+ deriving (Eq)++newtype SomeTVar = SomeTVar (TVar Any)+ deriving (Eq)++{-------------------------------------------------------------------------------+ Show instances++ Unfortunately reference cells are moved by GC, so we can't do much here;+ showing the address of the variable isn't particularly helpful.+-------------------------------------------------------------------------------}++instance Show SomeSTRef where+ show _ = "<STRef/IORef>" -- they look the same on the heap++instance Show SomeMVar where+ show _ = "<MVar>"++instance Show SomeTVar where+ show _ = "<TVar>"++instance Show SomeFun where+ show _ = "<Fun>"
+ tests/RecoverRttiTests.hs view
@@ -0,0 +1,17 @@+module Main (main) where++import Test.Tasty++import qualified Test.RecoverRTTI.Sanity+import qualified Test.RecoverRTTI.Classify+import qualified Test.RecoverRTTI.Show++main :: IO ()+main = defaultMain tests++tests :: TestTree+tests = testGroup "RecoverRttiTests" [+ Test.RecoverRTTI.Sanity.tests+ , Test.RecoverRTTI.Classify.tests+ , Test.RecoverRTTI.Show.tests+ ]
+ tests/Test/RecoverRTTI/Arbitrary.hs view
@@ -0,0 +1,603 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Test.RecoverRTTI.Arbitrary (+ ClassifiedGen(..)+ , arbitraryClassifiedGen+ -- * Example values of reference cells+ , exampleIORef+ , exampleSTRef+ , exampleMVar+ , exampleTVar+ ) where++import Control.Concurrent.MVar (newEmptyMVar)+import Control.Concurrent.STM (newTVarIO)+import Control.Monad+import Control.Monad.ST.Unsafe (unsafeSTToIO)+import Data.Bifunctor+import Data.IORef (newIORef)+import Data.Maybe (catMaybes)+import Data.SOP+import Data.SOP.Dict+import Data.STRef (newSTRef)+import Data.Tree (Tree)+import Data.Void+import GHC.Real+import System.IO.Unsafe (unsafePerformIO)+import Unsafe.Coerce (unsafeCoerce)++import qualified Data.Aeson as Aeson+import qualified Data.ByteString as BS.Strict+import qualified Data.ByteString.Lazy as BS.Lazy+import qualified Data.ByteString.Short as BS.Short+import qualified Data.IntMap as IntMap+import qualified Data.Map as Map+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Text as Text.Strict+import qualified Data.Text.Lazy as Text.Lazy+import qualified Data.Tree as Tree+import qualified Data.Vector as Vector++import Test.QuickCheck hiding (classify, NonEmpty)++import Debug.RecoverRTTI+import Debug.RecoverRTTI.Util+import Debug.RecoverRTTI.Util.TypeLevel++import Test.RecoverRTTI.ConcreteClassifier+import Test.RecoverRTTI.Orphans ()+import Test.RecoverRTTI.UserDefined++{-------------------------------------------------------------------------------+ Generic auxiliary+-------------------------------------------------------------------------------}++newtype SizedGen a = SizedGen (Int -> Gen a)+ deriving (Functor)++runSized :: Int -> SizedGen a -> Gen a+runSized n (SizedGen gen) = gen n++ignoreSize :: Gen a -> SizedGen a+ignoreSize gen = SizedGen $ \_sz -> gen++{-------------------------------------------------------------------------------+ Arbitrary instance+-------------------------------------------------------------------------------}++-- | Quickcheck generator along with a classifier+data ClassifiedGen a where+ ClassifiedGen ::+ (Show a, Eq a)+ => { -- | The classifier for the generator+ genClassifier :: ConcreteClassifier a++ -- | The classified generator itself+ --+ -- The size argument determines the maximum size of the /value/+ -- (as opposed to the maximum size of the /type/)+ , classifiedGen :: SizedGen a+ }+ -> ClassifiedGen a++canShowClassifiedGen :: ClassifiedGen a -> Dict Show a+canShowClassifiedGen ClassifiedGen{} = Dict++canEqClassifiedGen :: ClassifiedGen a -> Dict Eq a+canEqClassifiedGen ClassifiedGen{} = Dict++defaultClassifiedGen ::+ (Arbitrary a, Show a, Eq a)+ => ConcreteClassifier a+ -> ClassifiedGen a+defaultClassifiedGen cc = ClassifiedGen cc $ ignoreSize arbitrary++-- | Generated arbitrary classifier along with a generator for that value+--+-- NOTE: The @sz@ parameter limits the size of the /type tree/ (i.e., the number+-- of recursive calls to arbitraryClassifiedGen), /not/ the size of the+-- generated /values/.+arbitraryClassifiedGen :: Int -> Gen (Some ClassifiedGen)+arbitraryClassifiedGen typSz+ | typSz < 0 = error "arbitraryClassifiedGen: uhoh.. bug"+ | typSz == 0 = elements leaves+ | otherwise = oneof (elements leaves : catMaybes compound)+ where+ -- Leaves of the tree (values with no recursion)+ --+ -- Since there are the leaves, we don't need to check the size+ leaves :: [Some ClassifiedGen]+ leaves = concat [+ -- Primitive types+ [ Some $ defaultClassifiedGen CC_Bool+ , Some $ defaultClassifiedGen CC_Char+ , Some $ defaultClassifiedGen CC_Double+ , Some $ defaultClassifiedGen CC_Float+ , Some $ defaultClassifiedGen CC_Int+ , Some $ defaultClassifiedGen CC_Int16+ , Some $ defaultClassifiedGen CC_Int8+ , Some $ defaultClassifiedGen CC_Int32+ , Some $ defaultClassifiedGen CC_Int64+ , Some $ defaultClassifiedGen CC_Integer+ , Some $ defaultClassifiedGen CC_Ordering+ , Some $ defaultClassifiedGen CC_Unit+ , Some $ defaultClassifiedGen CC_Word+ , Some $ defaultClassifiedGen CC_Word8+ , Some $ defaultClassifiedGen CC_Word16+ , Some $ defaultClassifiedGen CC_Word32+ , Some $ defaultClassifiedGen CC_Word64+ ]++ -- Strings+ --+ -- Avoid generating the empty string (recognized as @[Void]@)+ , let mapList :: Arbitrary a => Int -> ([a] -> b) -> SizedGen b+ mapList minSize f = SizedGen $ \valSz -> do+ n <- choose (minSize, max minSize valSz) -- maybe valSz == 0+ f <$> vector n+ in [+ Some $ ClassifiedGen CC_String (mapList 1 id)+ , Some $ ClassifiedGen CC_BS_Strict (mapList 0 BS.Strict.pack)+ , Some $ ClassifiedGen CC_BS_Lazy (mapList 0 BS.Lazy.pack)+ , Some $ ClassifiedGen CC_BS_Short (mapList 0 BS.Short.pack)+ , Some $ ClassifiedGen CC_Text_Strict (mapList 0 Text.Strict.pack)+ , Some $ ClassifiedGen CC_Text_Lazy (mapList 0 Text.Lazy.pack)+ ]++ -- Aeson+ , [ Some $ ClassifiedGen CC_Value arbitraryAesonValue ]++ -- Reference cells+ , [ Some $ ClassifiedGen CC_STRef (ignoreSize $ pure exampleSTRef)+ , Some $ ClassifiedGen CC_STRef (ignoreSize $ pure exampleIORef)+ , Some $ ClassifiedGen CC_MVar (ignoreSize $ pure exampleMVar)+ , Some $ ClassifiedGen CC_TVar (ignoreSize $ pure exampleTVar)+ ]++ -- Functions+ --+ -- For functions we don't currently try to be clever and /generate/+ -- functions. Instead, we just try a few different categories.+ , map (\f -> Some $ ClassifiedGen CC_Fun (ignoreSize $ pure f)) [+ -- Parametrically polymorphic function+ unsafeCoerce (id :: Int -> Int)+ , unsafeCoerce (const :: Int -> Bool -> Int)+ -- Ad-hoc polymorphic function+ , unsafeCoerce (negate :: Int -> Int)+ , unsafeCoerce ((+) :: Int -> Int -> Int)+ -- Partial application+ , unsafeCoerce (const 1 :: Bool -> Int)+ , unsafeCoerce ((+) 1 :: Int -> Int)+ ]+ ]++ -- Compound+ --+ -- These are only used if @sz > 0@.+ compound :: [Maybe (Gen (Some ClassifiedGen))]+ compound = [+ -- Lists+ --+ -- We have to be careful not to generate @[Char]@, because this is+ -- inferred as @String@+ guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz - 1)+ genMaybeF+ (\case FJust CC_Char -> CC_String+ c -> CC_List c)+ (return [])+ (\(SizedGen gen) -> SizedGen $ \valSz -> do+ -- Pick number of list elements (don't generate empty list)+ n <- choose (1, 5)++ -- Then divide total size of each list element+ vectorOf n (gen (valSz `div` n))+ )+ a+ )++ -- Maybe+ , guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz - 1)+ genMaybeF CC_Maybe (return Nothing) (fmap Just) a+ )++ -- Either+ , guard (typSz >= 2) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz `div` 2)+ Some b <- arbitraryClassifiedGen (typSz `div` 2)+ genEitherF CC_Either (fmap Left) (fmap Right) a b+ )++ -- Ratio+ , guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz `div` 2)+ genF+ CC_Ratio+ (\(SizedGen gen) -> SizedGen $ \sz ->+ (:%) <$> gen (sz `div` 2) <*> gen (sz `div` 2)+ )+ a+ )++ -- Set+ -- For set we must pick an ordered type, so we just pick Int+ , return (do+ genMaybeF+ CC_Set+ (return Set.empty)+ -- Same strategy as for lists+ (\(SizedGen gen) -> SizedGen $ \valSz -> do+ n <- choose (1, 5)+ Set.fromList <$> vectorOf n (gen (valSz `div` n))+ )+ (defaultClassifiedGen CC_Int)+ )++ -- Map+ -- Pick Int for the keys, but randomly for the values+ , guard (typSz >= 1) >> (return $ do+ Some b <- arbitraryClassifiedGen (typSz - 1)+ genMaybePairF+ CC_Map+ (return Map.empty)+ (\(SizedGen genX) (SizedGen genY) -> SizedGen $ \valSz -> do+ n <- choose (1, 5)+ Map.fromList <$> vectorOf n (+ (,) <$> genX (valSz `div` n `div` 2)+ <*> genY (valSz `div` n `div` 2)+ )+ )+ (defaultClassifiedGen CC_Int)+ b+ )++ -- IntSet+ , return $ return $ Some (defaultClassifiedGen CC_IntSet)++ -- IntMap+ , guard (typSz >= 1) >> (return $ do+ Some b <- arbitraryClassifiedGen (typSz - 1)+ genMaybeF+ CC_IntMap+ (return IntMap.empty)+ (\(SizedGen genY) -> SizedGen $ \valSz -> do+ n <- choose (1, 5)+ IntMap.fromList <$> vectorOf n (+ (,) <$> arbitrary+ <*> genY (valSz `div` n)+ )+ )+ b+ )++ -- Sequence+ , guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz - 1)+ genMaybeF+ CC_Sequence+ (return Seq.empty)+ (\(SizedGen genX) -> SizedGen $ \valSz -> do+ n <- choose (1, 5)+ Seq.fromList <$> vectorOf n (genX (valSz `div` n))+ )+ a+ )++ -- Tree+ , guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz - 1)+ genF+ CC_Tree+ (\(SizedGen genX) -> SizedGen $ \valSz -> do+ n <- choose (1, 5)+ mkSomeTree <$> vectorOf n (genX (valSz `div` n))+ )+ a+ )++ --+ -- User-defined+ --++ , guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz - 1)+ genMaybeF+ CC_User_NonRec+ (NR1 <$> arbitrary)+ (\gen -> SizedGen $ \valSz ->+ NR2 <$> runSized valSz gen <*> arbitrary+ )+ a+ )++ , guard (typSz >= 1) >> (return $ do+ Some a <- arbitraryClassifiedGen (typSz - 1)+ genMaybeF+ CC_User_Rec+ (return RNil)+ (\gen -> SizedGen $ \valSz -> do+ -- Similar strategy as for lists+ n <- choose (1, 5)+ recursiveFromList <$> vectorOf n (runSized (valSz `div` n) gen)+ )+ a+ )++ , return $ do+ return $ Some $ ClassifiedGen (CC_User_Unlifted (FJust CC_Unit)) $ SizedGen $ \_ ->+ return exampleContainsUnlifted++ -- Tuples+ , guard (typSz >= 2) >> (return $+ arbitraryTuple typSz $ \np ->+ case ( all_NP (hmap canShowClassifiedGen np)+ , all_NP (hmap canEqClassifiedGen np)+ ) of+ (Dict, Dict) ->+ return . Some $ ClassifiedGen {+ genClassifier =+ CC_Tuple (ConcreteClassifiers (hmap genClassifier np))+ , classifiedGen = SizedGen $ \valSz -> do+ let valSz' = valSz `div` lengthSList np+ tupleFromNP <$>+ hsequence(hmap (runSized valSz' . classifiedGen) np)+ }+ )+ ]++ genMaybeF ::+ ( forall x. Show x => Show (f x)+ , forall x. Eq x => Eq (f x)+ )+ => (forall x. MaybeF ConcreteClassifier x -> ConcreteClassifier (f x))+ -> Gen (f Void)+ -> (SizedGen a -> SizedGen (f a))+ -> ClassifiedGen a -> Gen (Some ClassifiedGen)+ genMaybeF cc genNothing genJust (ClassifiedGen cA genA) =+ elements [+ Some $ ClassifiedGen (cc FNothing) (ignoreSize $ genNothing)+ , Some $ ClassifiedGen (cc (FJust cA)) (genJust genA)+ ]++ genEitherF ::+ ( forall x y. (Show x, Show y) => Show (f x y)+ , forall x y. (Eq x, Eq y) => Eq (f x y)+ )+ => (forall x y. EitherF ConcreteClassifier x y -> ConcreteClassifier (f x y))+ -> (SizedGen a -> SizedGen (f a Void))+ -> (SizedGen b -> SizedGen (f Void b))+ -> ClassifiedGen a+ -> ClassifiedGen b+ -> Gen (Some ClassifiedGen)+ genEitherF cc genLeft genRight (ClassifiedGen cA genA) (ClassifiedGen cB genB) =+ elements [+ Some $ ClassifiedGen (cc (FLeft cA)) (genLeft genA)+ , Some $ ClassifiedGen (cc (FRight cB)) (genRight genB)+ ]++ genMaybePairF ::+ ( forall x y. (Show x, Show y) => Show (f x y)+ , forall x y. (Eq x, Eq y) => Eq (f x y)+ )+ => (forall x y. MaybePairF ConcreteClassifier x y -> ConcreteClassifier (f x y))+ -> Gen (f Void Void)+ -> (SizedGen a -> SizedGen b -> SizedGen (f a b))+ -> ClassifiedGen a -> ClassifiedGen b -> Gen (Some ClassifiedGen)+ genMaybePairF cc genNothing genJust (ClassifiedGen cA genA) (ClassifiedGen cB genB) =+ elements [+ Some $ ClassifiedGen (cc FNothingPair) (ignoreSize $ genNothing)+ , Some $ ClassifiedGen (cc (FJustPair cA cB)) (genJust genA genB)+ ]++ genF ::+ ( forall x. Show x => Show (f x)+ , forall x. Eq x => Eq (f x)+ )+ => (forall x. ConcreteClassifier x -> ConcreteClassifier (f x))+ -> (SizedGen a -> SizedGen (f a))+ -> ClassifiedGen a -> Gen (Some ClassifiedGen)+ genF cc gen (ClassifiedGen cA genA) = return $+ Some $ ClassifiedGen (cc cA) (gen genA)++ -- We check that we cover all cases of 'Classifier' rather than+ -- 'ConcreteClassifier': it is important that we generate test cases for+ -- everything we classify in the main library.+ _checkAllCases :: Classifier a -> ()+ _checkAllCases = \case+ -- Primitive types++ C_Bool -> ()+ C_Char -> ()+ C_Double -> ()+ C_Float -> ()+ C_Int -> ()+ C_Int16 -> ()+ C_Int8 -> ()+ C_Int32 -> ()+ C_Int64 -> ()+ C_Integer -> ()+ C_Ordering -> ()+ C_Unit -> ()+ C_Word -> ()+ C_Word8 -> ()+ C_Word16 -> ()+ C_Word32 -> ()+ C_Word64 -> ()++ -- String types++ C_String -> ()+ C_BS_Strict -> ()+ C_BS_Lazy -> ()+ C_BS_Short -> ()+ C_Text_Strict -> ()+ C_Text_Lazy -> ()++ -- Aeson++ C_Value -> ()++ -- Compound++ C_Maybe{} -> ()+ C_Either{} -> ()+ C_List{} -> ()+ C_Ratio{} -> ()+ C_Set{} -> ()+ C_Map{} -> ()+ C_IntSet{} -> ()+ C_IntMap{} -> ()+ C_Tuple{} -> ()+ C_Sequence{} -> ()+ C_Tree{} -> ()++ -- Reference cells++ C_STRef -> ()+ C_TVar -> ()+ C_MVar -> ()++ -- Functions++ C_Fun -> ()++ -- User-defined++ C_Custom{} -> ()++-- | Generate arbitrary tuple size+arbitraryTuple :: forall r.+ Int -- ^ Maximum type size (should be at least 2)+ -> (forall xs.+ (SListI xs, IsValidSize (Length xs))+ => NP ClassifiedGen xs -> Gen r+ )+ -> Gen r+arbitraryTuple = \typSz k -> do+ tupleSz <- choose (2, min typSz 62)+ let typSz' = typSz `div` tupleSz+ case toValidSize tupleSz of+ Nothing ->+ error "arbitraryTuple: impossible, this is a valid tuple size"+ Just (Some valid@(ValidSize n _)) ->+ go typSz' n $ \(np :: NP ClassifiedGen xs) ->+ case liftValidSize (valid :: ValidSize (Length xs))+ of Dict -> k np+ where+ go :: Int+ -> Sing (n :: Nat)+ -> (forall xs.+ (SListI xs, Length xs ~ n)+ => NP ClassifiedGen xs -> Gen r+ )+ -> Gen r+ go _ SZ k = k Nil+ go typSz' (SS n) k = do+ Some c <- arbitraryClassifiedGen typSz'+ go typSz' n $ \cs -> k (c :* cs)++instance Arbitrary (Some Value) where+ arbitrary = sized $ \sz -> do+ -- @sz@ will range from 0..100, but we don't want to generate types that+ -- large+ Some (ClassifiedGen cc gen) <- arbitraryClassifiedGen (sz `div` 10)++ -- For the values however we want to be able to generate larger trees+ Some . Value cc <$> runSized sz gen++{-------------------------------------------------------------------------------+ Auxiliary tree functions+-------------------------------------------------------------------------------}++mkSomeTree :: [a] -> Tree a+mkSomeTree [] = error "mkSomeTree: empty"+mkSomeTree [x] = Tree.Node x []+mkSomeTree [x, y] = Tree.Node x [Tree.Node y []]+mkSomeTree (x : xs) =+ let (left, right) = split xs+ in Tree.Node x [mkSomeTree left, mkSomeTree right]++-- | Split list into halves+--+-- If the input has at least two elements, neither list will be empty+--+-- > split "abcde" == ("ace","bd")+split :: [a] -> ([a], [a])+split [] = ([], [])+split (x:xs) = first (x:) $ splot xs++-- | Auxiliary to 'split'+splot :: [a] -> ([a], [a])+splot [] = ([], [])+splot (x:xs) = second (x:) $ split xs++{-------------------------------------------------------------------------------+ Auxiliary Aeson+-------------------------------------------------------------------------------}++arbitraryAesonValue :: SizedGen Aeson.Value+arbitraryAesonValue = SizedGen $ go+ where+ go :: Int -> Gen Aeson.Value+ go 0 = oneof nonRecursive+ go sz = oneof (nonRecursive ++ recursive sz)++ nonRecursive :: [Gen Aeson.Value]+ nonRecursive = [+ Aeson.String . Text.Strict.pack <$> arbitrary+ , Aeson.Number . fromInteger <$> arbitrary+ , Aeson.Bool <$> arbitrary+ , return Aeson.Null+ ]++ recursive :: Int -> [Gen Aeson.Value]+ recursive sz = [+ do n <- choose (0, 5)+ Aeson.Array . Vector.fromList <$> replicateM n (go (sz `div` n))+ , do n <- choose (0, 5)+ Aeson.object <$> replicateM n (+ (Aeson..=)+ <$> fieldName+ <*> go (sz `div` n)+ )+ ]++ -- We're not interested in testing crazy values+ fieldName :: Gen Text.Strict.Text+ fieldName = elements ["a", "b", "c"]++{-------------------------------------------------------------------------------+ Some global variables, which we use only as input to the tests+-------------------------------------------------------------------------------}++exampleIORef :: SomeSTRef+{-# NOINLINE exampleIORef #-}+exampleIORef = unsafePerformIO $+ -- IORef is indistinguishable from STRef on the heap+ unsafeCoerce <$> newIORef (unsafeCoerce ())++exampleSTRef :: SomeSTRef+exampleSTRef = unsafePerformIO $ unsafeSTToIO $+ unsafeCoerce <$> newSTRef (unsafeCoerce ())++exampleMVar :: SomeMVar+{-# NOINLINE exampleMVar #-}+exampleMVar = unsafePerformIO $+ SomeMVar <$> newEmptyMVar++exampleTVar :: SomeTVar+{-# NOINLINE exampleTVar #-}+exampleTVar = unsafePerformIO $+ SomeTVar <$> newTVarIO (unsafeCoerce ())
+ tests/Test/RecoverRTTI/Classify.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- | Verify we infer the right classifier+module Test.RecoverRTTI.Classify (tests) where++import Control.Monad.Except+import Data.Ratio+import Data.SOP+import Data.Type.Equality++import qualified Data.Aeson as Aeson+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.Map as Map+import qualified Data.Sequence as Seq+import qualified Data.Set as Set+import qualified Data.Tree as Tree++import Test.Tasty+import Test.Tasty.QuickCheck hiding (classify, NonEmpty)++import Debug.RecoverRTTI+import Debug.RecoverRTTI.Util++import Test.RecoverRTTI.Arbitrary+import Test.RecoverRTTI.ConcreteClassifier+import Test.RecoverRTTI.Orphans ()+import Test.RecoverRTTI.Staged+import Test.RecoverRTTI.UserDefined++tests :: TestTree+tests = testGroup "Test.RecoverRTTI.Classify" [+ testProperty "constants" prop_constants+ , testProperty "arbitrary" prop_arbitrary+ ]++-- | Test using manually specified examples+--+-- For " normal " code it doesn't matter if something is generated or not,+-- but their on-heap representation may be different, and this may effect the+-- RTTI recovery.+prop_constants :: Property+prop_constants = withMaxSuccess 1 $ conjoin [+ -- Primitive types++ compareClassifier $ Value CC_Bool True+ , compareClassifier $ Value CC_Bool False+ , compareClassifier $ Value CC_Char 'a'+ , compareClassifier $ Value CC_Double 1.25+ , compareClassifier $ Value CC_Float 1.25+ , compareClassifier $ Value CC_Int 1234+ , compareClassifier $ Value CC_Int (-1234)+ , compareClassifier $ Value CC_Int8 123+ , compareClassifier $ Value CC_Int16 1234+ , compareClassifier $ Value CC_Int32 1234+ , compareClassifier $ Value CC_Int64 1234+ , compareClassifier $ Value CC_Integer 1234+ , compareClassifier $ Value CC_Integer (succ (fromIntegral (maxBound :: Int)))+ , compareClassifier $ Value CC_Integer (pred (fromIntegral (minBound :: Int)))+ , compareClassifier $ Value CC_Ordering LT+ , compareClassifier $ Value CC_Ordering GT+ , compareClassifier $ Value CC_Ordering EQ+ , compareClassifier $ Value CC_Unit ()+ , compareClassifier $ Value CC_Word 1234+ , compareClassifier $ Value CC_Word8 123+ , compareClassifier $ Value CC_Word16 134+ , compareClassifier $ Value CC_Word32 1234+ , compareClassifier $ Value CC_Word64 1234++ -- String types+ --+ -- We skip the empty string, because we infer that as @CC_List Empty@++ , compareClassifier $ Value CC_String "abcdefg"+ , compareClassifier $ Value CC_BS_Strict ""+ , compareClassifier $ Value CC_BS_Strict "abcdefg"+ , compareClassifier $ Value CC_BS_Lazy ""+ , compareClassifier $ Value CC_BS_Lazy "abcdefg"+ , compareClassifier $ Value CC_BS_Short ""+ , compareClassifier $ Value CC_BS_Short "abcdefg"+ , compareClassifier $ Value CC_Text_Strict ""+ , compareClassifier $ Value CC_Text_Strict "abcdefg"+ , compareClassifier $ Value CC_Text_Lazy ""+ , compareClassifier $ Value CC_Text_Lazy "abcdefg"++ -- Aeson++ , compareClassifier $ Value CC_Value (Aeson.object [("x" Aeson..= True)])++ -- Compound++ , compareClassifier $ Value (CC_Maybe FNothing) Nothing+ , compareClassifier $ Value (CC_Maybe (FJust CC_Int)) (Just 3)++ , compareClassifier $ Value (CC_Either (FLeft CC_Int)) (Left 3)+ , compareClassifier $ Value (CC_Either (FRight CC_Bool)) (Right True)++ , compareClassifier $ Value (CC_List FNothing) []+ , compareClassifier $ Value (CC_List (FJust CC_Int)) [1, 2, 3]++ , compareClassifier $ Value (CC_Tuple (ConcreteClassifiers (CC_Int :* CC_Char :* Nil))) (WrappedTuple (4, 'a'))+ , compareClassifier $ Value (CC_Tuple (ConcreteClassifiers (CC_Int :* CC_Char :* CC_Bool :* Nil))) (WrappedTuple (4, 'a', True))++ , compareClassifier $ Value (CC_Ratio CC_Integer) (1 % 2)++ , compareClassifier $ Value (CC_Set FNothing) Set.empty+ , compareClassifier $ Value (CC_Set (FJust CC_Int)) (Set.fromList [1, 2, 3] )++ , compareClassifier $ Value (CC_Map FNothingPair) Map.empty+ , compareClassifier $ Value (CC_Map (FJustPair CC_Int CC_Char)) (Map.fromList [(1, 'a'), (2, 'b')])++ , compareClassifier $ Value CC_IntSet IntSet.empty+ , compareClassifier $ Value CC_IntSet (IntSet.fromList [1, 2, 3])++ , compareClassifier $ Value (CC_IntMap FNothing) IntMap.empty+ , compareClassifier $ Value (CC_IntMap (FJust CC_Char)) (IntMap.fromList [(1, 'a'), (2, 'b')])++ , compareClassifier $ Value (CC_Sequence FNothing) Seq.empty+ , compareClassifier $ Value (CC_Sequence (FJust CC_Int)) (Seq.fromList [1, 2, 3])++ , compareClassifier $ Value (CC_Tree CC_Int) (Tree.Node 1 [])++ -- Reference cells++ , compareClassifier $ Value CC_STRef exampleIORef+ , compareClassifier $ Value CC_STRef exampleSTRef+ , compareClassifier $ Value CC_MVar exampleMVar+ , compareClassifier $ Value CC_TVar exampleTVar++ -- Functions++ , compareClassifier $ Value CC_Fun (SomeFun id)++ -- User defined++ , compareClassifier $ Value (CC_User_NonRec FNothing) (NR1 1234)+ , compareClassifier $ Value (CC_User_NonRec (FJust CC_Char)) (NR2 'a' True)+ , compareClassifier $ Value (CC_User_Rec FNothing) RNil+ , compareClassifier $ Value (CC_User_Rec (FJust CC_Char)) (RCons 'a' RNil)+ , compareClassifier $ Value (CC_User_Unlifted (FJust CC_Unit)) exampleContainsUnlifted+ ]+ where+ _checkAllCases :: ConcreteClassifier a -> ()+ _checkAllCases = \case+ -- Primitive types++ CC_Bool -> ()+ CC_Char -> ()+ CC_Double -> ()+ CC_Float -> ()+ CC_Int -> ()+ CC_Int8 -> ()+ CC_Int16 -> ()+ CC_Int32 -> ()+ CC_Int64 -> ()+ CC_Integer -> ()+ CC_Ordering -> ()+ CC_Unit -> ()+ CC_Word -> ()+ CC_Word8 -> ()+ CC_Word16 -> ()+ CC_Word32 -> ()+ CC_Word64 -> ()++ -- String types++ CC_String -> ()+ CC_BS_Strict -> ()+ CC_BS_Lazy -> ()+ CC_BS_Short -> ()+ CC_Text_Strict -> ()+ CC_Text_Lazy -> ()++ -- Aeson++ CC_Value -> ()++ -- Compound++ CC_Maybe{} -> ()+ CC_Either{} -> ()+ CC_List{} -> ()+ CC_Ratio{} -> ()+ CC_Set{} -> ()+ CC_Map{} -> ()+ CC_IntSet{} -> ()+ CC_IntMap{} -> ()+ CC_Sequence{} -> ()+ CC_Tree{} -> ()+ CC_Tuple{} -> ()++ -- Functions++ CC_Fun{} -> ()++ -- Reference cells++ CC_STRef -> ()+ CC_TVar -> ()+ CC_MVar -> ()++ -- User-defined++ CC_User_NonRec{} -> ()+ CC_User_Rec{} -> ()+ CC_User_Unlifted{} -> ()++-- | Test using arbitrary values+prop_arbitrary :: Some Value -> Property+prop_arbitrary (Some v) = compareClassifier v++-- | Compare given to inferred classifier+--+-- The tests in this module differ only in how the produce the 'Value's.+compareClassifier :: Value a -> Property+compareClassifier = \(Value cc x) ->+ counterexample ("Generated classifier: " ++ show cc)+ $ case runExcept $ classifyThenReclassify x of+ Left err ->+ counterexample ("Failed to reclassify. Error: " ++ err)+ $ property False+ Right (Reclassified cc' f) ->+ case sameConcreteClassifier cc cc' of+ Nothing ->+ counterexample ("Inferred different classifier: " ++ show cc')+ $ property False+ Just Refl ->+ x === f x
+ tests/Test/RecoverRTTI/ConcreteClassifier.hs view
@@ -0,0 +1,428 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}++module Test.RecoverRTTI.ConcreteClassifier (+ -- * Concrete classifier+ ConcreteClassifier(..)+ , sameConcreteClassifier+ , ConcreteClassifiers(..)+ , classifierSize+ -- * Values+ , Value(..)+ ) where++import Data.Int+import Data.IntMap (IntMap)+import Data.IntSet (IntSet)+import Data.Kind+import Data.Map (Map)+import Data.Ratio+import Data.Sequence (Seq)+import Data.Set (Set)+import Data.SOP+import Data.SOP.Dict+import Data.Tree (Tree)+import Data.Type.Equality+import Data.Word++import qualified Data.Aeson as Aeson+import qualified Data.ByteString as BS.Strict+import qualified Data.ByteString.Lazy as BS.Lazy+import qualified Data.ByteString.Short as BS.Short+import qualified Data.Text as Text.Strict+import qualified Data.Text.Lazy as Text.Lazy++import Debug.RecoverRTTI+import Debug.RecoverRTTI.Util+import Debug.RecoverRTTI.Util.TypeLevel++import Test.RecoverRTTI.UserDefined++{-------------------------------------------------------------------------------+ Concrete classifier++ The difference between the " concrete " classifier and the 'Classifier' from+ the main library is that the former has explicit cases for user-defined types,+ and the latter doesn't (merely classifying them as 'UserDefined').++ In "Test.RecoverRRTI.Staged" we show that we can do staged inference,+ using 'classify' repeatedly to recover /all/ (concrete) type information+ from the type information returned by 'classify' (/if/ we have full+ information about which user-defined types we're interested in).+-------------------------------------------------------------------------------}++-- | Like 'Classifier', but with no guess-work and concrete types+data ConcreteClassifier (a :: Type) :: Type where+ -- Primitive types++ CC_Bool :: ConcreteClassifier Bool+ CC_Char :: ConcreteClassifier Char+ CC_Double :: ConcreteClassifier Double+ CC_Float :: ConcreteClassifier Float+ CC_Int :: ConcreteClassifier Int+ CC_Int8 :: ConcreteClassifier Int8+ CC_Int16 :: ConcreteClassifier Int16+ CC_Int32 :: ConcreteClassifier Int32+ CC_Int64 :: ConcreteClassifier Int64+ CC_Integer :: ConcreteClassifier Integer+ CC_Ordering :: ConcreteClassifier Ordering+ CC_Unit :: ConcreteClassifier ()+ CC_Word :: ConcreteClassifier Word+ CC_Word8 :: ConcreteClassifier Word8+ CC_Word16 :: ConcreteClassifier Word16+ CC_Word32 :: ConcreteClassifier Word32+ CC_Word64 :: ConcreteClassifier Word64++ -- Text types++ CC_String :: ConcreteClassifier String+ CC_BS_Strict :: ConcreteClassifier BS.Strict.ByteString+ CC_BS_Lazy :: ConcreteClassifier BS.Lazy.ByteString+ CC_BS_Short :: ConcreteClassifier BS.Short.ShortByteString+ CC_Text_Strict :: ConcreteClassifier Text.Strict.Text+ CC_Text_Lazy :: ConcreteClassifier Text.Lazy.Text++ -- Aeson++ CC_Value :: ConcreteClassifier Aeson.Value++ -- Compound++ CC_Maybe :: MaybeF ConcreteClassifier a -> ConcreteClassifier (Maybe a)+ CC_Either :: EitherF ConcreteClassifier a b -> ConcreteClassifier (Either a b)+ CC_List :: MaybeF ConcreteClassifier a -> ConcreteClassifier [a]+ CC_Ratio :: ConcreteClassifier a -> ConcreteClassifier (Ratio a)+ CC_Set :: MaybeF ConcreteClassifier a -> ConcreteClassifier (Set a)+ CC_Map :: MaybePairF ConcreteClassifier a b -> ConcreteClassifier (Map a b)+ CC_IntSet :: ConcreteClassifier IntSet+ CC_IntMap :: MaybeF ConcreteClassifier a -> ConcreteClassifier (IntMap a)+ CC_Sequence :: MaybeF ConcreteClassifier a -> ConcreteClassifier (Seq a)+ CC_Tree :: ConcreteClassifier a -> ConcreteClassifier (Tree a)++ CC_Tuple ::+ (SListI xs, IsValidSize (Length xs))+ => ConcreteClassifiers xs -> ConcreteClassifier (WrappedTuple xs)++ -- Functions++ CC_Fun :: ConcreteClassifier SomeFun++ -- Reference cells++ CC_STRef :: ConcreteClassifier SomeSTRef+ CC_TVar :: ConcreteClassifier SomeTVar+ CC_MVar :: ConcreteClassifier SomeMVar++ -- User-defined++ CC_User_NonRec :: MaybeF ConcreteClassifier a -> ConcreteClassifier (NonRecursive a)+ CC_User_Rec :: MaybeF ConcreteClassifier a -> ConcreteClassifier (Recursive a)+ CC_User_Unlifted :: MaybeF ConcreteClassifier a -> ConcreteClassifier (ContainsUnlifted a)++newtype ConcreteClassifiers xs = ConcreteClassifiers (NP ConcreteClassifier xs)++deriving instance Show (ConcreteClassifier a)+deriving instance Show (MaybeF ConcreteClassifier a)+deriving instance Show (EitherF ConcreteClassifier a b)+deriving instance Show (MaybePairF ConcreteClassifier a b)++instance SListI xs => Show (ConcreteClassifiers xs) where+ show (ConcreteClassifiers xs) = go (hpure Dict)+ where+ go :: NP (Dict (Compose Show ConcreteClassifier)) xs -> String+ go dicts =+ case all_NP dicts of+ Dict -> "(" ++ show xs ++ ")"++{-------------------------------------------------------------------------------+ Size of the classifier++ Mostly used for sanity checking the generator+-------------------------------------------------------------------------------}++classifierSize :: ConcreteClassifier a -> Int+classifierSize = go+ where+ go :: ConcreteClassifier a -> Int++ -- Primitive types+ go CC_Bool = 1+ go CC_Char = 1+ go CC_Double = 1+ go CC_Float = 1+ go CC_Int = 1+ go CC_Int8 = 1+ go CC_Int16 = 1+ go CC_Int32 = 1+ go CC_Int64 = 1+ go CC_Integer = 1+ go CC_Ordering = 1+ go CC_Unit = 1+ go CC_Word = 1+ go CC_Word8 = 1+ go CC_Word16 = 1+ go CC_Word32 = 1+ go CC_Word64 = 1++ -- Text types+ go CC_String = 1+ go CC_BS_Strict = 1+ go CC_BS_Lazy = 1+ go CC_BS_Short = 1+ go CC_Text_Strict = 1+ go CC_Text_Lazy = 1++ -- Aeson+ go CC_Value = 1++ -- Compound++ go (CC_Maybe c) = 1 + goMaybeF c+ go (CC_Either c) = 1 + goEitherF c+ go (CC_List c) = 1 + goMaybeF c+ go (CC_Ratio c) = 1 + go c+ go (CC_Set c) = 1 + goMaybeF c+ go (CC_Map c) = 1 + goMaybePairF c+ go CC_IntSet = 1+ go (CC_IntMap c) = 1 + goMaybeF c+ go (CC_Sequence c) = 1 + goMaybeF c+ go (CC_Tree c) = 1 + go c++ go (CC_Tuple (ConcreteClassifiers cs)) =+ 1 + sum (hcollapse (hmap (K . go) cs))++ -- Functions+ go CC_Fun = 1++ -- Reference cells+ go CC_STRef = 1+ go CC_TVar = 1+ go CC_MVar = 1++ -- User-defined+ go (CC_User_NonRec c) = 1 + goMaybeF c+ go (CC_User_Rec c) = 1 + goMaybeF c+ go (CC_User_Unlifted c) = 1 + goMaybeF c ++ goMaybeF :: MaybeF ConcreteClassifier a -> Int+ goMaybeF FNothing = 0+ goMaybeF (FJust c) = go c++ goEitherF :: EitherF ConcreteClassifier a b -> Int+ goEitherF (FLeft c) = go c+ goEitherF (FRight c) = go c++ goMaybePairF :: MaybePairF ConcreteClassifier a b -> Int+ goMaybePairF FNothingPair = 0+ goMaybePairF (FJustPair c c') = go c + go c'++{-------------------------------------------------------------------------------+ Values+-------------------------------------------------------------------------------}++-- | Like 'Classified', but using 'ConcreteClassifier'+--+-- For convenience, we also include some constraints here, even though they+-- are in fact derivable from the classifier+data Value a where+ Value :: (Show a, Eq a) => ConcreteClassifier a -> a -> Value a++deriving instance Show (Value a)+deriving instance Show (Some Value)++{-------------------------------------------------------------------------------+ Equality+-------------------------------------------------------------------------------}++-- | Check that two classifiers are the same+--+-- If they are the same, additionally return a proof that that means the+-- /types/ they classify must be equal (note that equality on the classifiers+-- is strictly stronger than equality on the types: for example, non-empty+-- and empty lists have different classifiers, but classify the same type).+sameConcreteClassifier ::+ ConcreteClassifier a+ -> ConcreteClassifier b+ -> Maybe (a :~: b)+sameConcreteClassifier = go+ where+ go :: ConcreteClassifier a -> ConcreteClassifier b -> Maybe (a :~: b)+ go CC_Bool CC_Bool = Just Refl+ go CC_Char CC_Char = Just Refl+ go CC_Double CC_Double = Just Refl+ go CC_Float CC_Float = Just Refl+ go CC_Int CC_Int = Just Refl+ go CC_Int8 CC_Int8 = Just Refl+ go CC_Int16 CC_Int16 = Just Refl+ go CC_Int32 CC_Int32 = Just Refl+ go CC_Int64 CC_Int64 = Just Refl+ go CC_Integer CC_Integer = Just Refl+ go CC_Ordering CC_Ordering = Just Refl+ go CC_Unit CC_Unit = Just Refl+ go CC_Word CC_Word = Just Refl+ go CC_Word8 CC_Word8 = Just Refl+ go CC_Word16 CC_Word16 = Just Refl+ go CC_Word32 CC_Word32 = Just Refl+ go CC_Word64 CC_Word64 = Just Refl++ -- String types++ go CC_String CC_String = Just Refl+ go CC_BS_Strict CC_BS_Strict = Just Refl+ go CC_BS_Lazy CC_BS_Lazy = Just Refl+ go CC_BS_Short CC_BS_Short = Just Refl+ go CC_Text_Strict CC_Text_Strict = Just Refl+ go CC_Text_Lazy CC_Text_Lazy = Just Refl++ -- Aeson++ go CC_Value CC_Value = Just Refl++ -- Compound++ go (CC_Maybe c) (CC_Maybe c') = goMaybeF c c'+ go (CC_Either c) (CC_Either c') = goEitherF c c'+ go (CC_List c) (CC_List c') = goMaybeF c c'+ go (CC_Ratio c) (CC_Ratio c') = goF c c'+ go (CC_Set c) (CC_Set c') = goMaybeF c c'+ go (CC_Map c) (CC_Map c') = goMaybePairF c c'+ go CC_IntSet CC_IntSet = Just Refl+ go (CC_IntMap c) (CC_IntMap c') = goMaybeF c c'+ go (CC_Sequence c) (CC_Sequence c') = goMaybeF c c'+ go (CC_Tree c) (CC_Tree c') = goF c c'++ go (CC_Tuple (ConcreteClassifiers cs))+ (CC_Tuple (ConcreteClassifiers cs')) = (\Refl -> Refl) <$> goList cs cs'++ -- Reference cells++ go CC_STRef CC_STRef = Just Refl+ go CC_TVar CC_TVar = Just Refl+ go CC_MVar CC_MVar = Just Refl++ -- Functions++ go CC_Fun CC_Fun = Just Refl++ -- User-defined++ go (CC_User_NonRec c) (CC_User_NonRec c') = goMaybeF c c'+ go (CC_User_Rec c) (CC_User_Rec c') = goMaybeF c c'+ go (CC_User_Unlifted c) (CC_User_Unlifted c') = goMaybeF c c'++ -- Otherwise, not equal++ go _ _ = Nothing++ goMaybeF ::+ MaybeF ConcreteClassifier x+ -> MaybeF ConcreteClassifier x'+ -> Maybe (f x :~: f x')+ goMaybeF FNothing FNothing = Just Refl+ goMaybeF (FJust x) (FJust x') = (\Refl -> Refl) <$> go x x'+ goMaybeF _ _ = Nothing++ goEitherF ::+ EitherF ConcreteClassifier x y+ -> EitherF ConcreteClassifier x' y'+ -> Maybe (f x y :~: f x' y')+ goEitherF (FLeft x) (FLeft x') = (\Refl -> Refl) <$> go x x'+ goEitherF (FRight y) (FRight y') = (\Refl -> Refl) <$> go y y'+ goEitherF (FLeft _) (FRight _ ) = Nothing+ goEitherF (FRight _) (FLeft _ ) = Nothing++ goF ::+ ConcreteClassifier x+ -> ConcreteClassifier x'+ -> Maybe (f x :~: f x')+ goF x x' = (\Refl -> Refl) <$> go x x'++ goMaybePairF ::+ MaybePairF ConcreteClassifier x y+ -> MaybePairF ConcreteClassifier x' y'+ -> Maybe (f x y :~: f x' y')+ goMaybePairF FNothingPair FNothingPair = Just Refl+ goMaybePairF (FJustPair x y) (FJustPair x' y') = (\Refl Refl -> Refl) <$> go x x' <*> go y y'+ goMaybePairF _ _ = Nothing++ goList ::+ NP ConcreteClassifier xs+ -> NP ConcreteClassifier ys+ -> Maybe (xs :~: ys)+ goList Nil Nil = Just Refl+ goList (x :* xs) (y :* ys) = (\Refl Refl -> Refl) <$> go x y <*> goList xs ys+ goList Nil (_ :* _) = Nothing+ goList (_ :* _) Nil = Nothing++ -- Make sure we get a warning if we add another constructor+ _checkAllCases :: ConcreteClassifier a -> ()+ _checkAllCases = \case+ -- Primitive types++ CC_Bool -> ()+ CC_Char -> ()+ CC_Double -> ()+ CC_Float -> ()+ CC_Int -> ()+ CC_Int8 -> ()+ CC_Int16 -> ()+ CC_Int32 -> ()+ CC_Int64 -> ()+ CC_Integer -> ()+ CC_Ordering -> ()+ CC_Unit -> ()+ CC_Word -> ()+ CC_Word8 -> ()+ CC_Word16 -> ()+ CC_Word32 -> ()+ CC_Word64 -> ()++ -- String types++ CC_String -> ()+ CC_BS_Strict -> ()+ CC_BS_Lazy -> ()+ CC_BS_Short -> ()+ CC_Text_Strict -> ()+ CC_Text_Lazy -> ()++ -- Aeson++ CC_Value -> ()++ -- Compound++ CC_Maybe{} -> ()+ CC_Either{} -> ()+ CC_List{} -> ()+ CC_Ratio{} -> ()+ CC_Set{} -> ()+ CC_Map{} -> ()+ CC_IntSet{} -> ()+ CC_IntMap{} -> ()+ CC_Tuple{} -> ()+ CC_Sequence{} -> ()+ CC_Tree{} -> ()++ -- Reference cells++ CC_STRef -> ()+ CC_TVar -> ()+ CC_MVar -> ()++ -- Functions++ CC_Fun -> ()++ -- User-defined++ CC_User_NonRec{} -> ()+ CC_User_Rec{} -> ()+ CC_User_Unlifted{} -> ()
+ tests/Test/RecoverRTTI/Orphans.hs view
@@ -0,0 +1,14 @@+module Test.RecoverRTTI.Orphans () where++import Debug.RecoverRTTI++-- | Degenerate 'Eq' instance for functions that always says 'True'+--+-- When we compare values up to the coercion returned by 'reclassify', we need+-- an 'Eq' instance. We can't compare functions in any meaningful way though,+-- and so we just return 'True' here no matter what.+--+-- This is an orphan defined in the test suite only, so that users of the+-- library don't have acccess to this (misleading) instance.+instance Eq SomeFun where+ _ == _ = True
+ tests/Test/RecoverRTTI/Sanity.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE NamedFieldPuns #-}++module Test.RecoverRTTI.Sanity (tests) where++import Debug.RecoverRTTI.Util++import Test.Tasty+import Test.Tasty.QuickCheck++import Test.RecoverRTTI.Arbitrary+import Test.RecoverRTTI.ConcreteClassifier++tests :: TestTree+tests = testGroup "Test.RecoverRTTI.Sanity" [+ testProperty "typeSize" prop_typeSize+ ]++prop_typeSize :: Property+prop_typeSize =+ forAll (Blind <$> arbitraryClassifiedGen 10) $+ \(Blind (Some ClassifiedGen{genClassifier})) ->+ counterexample ("classifier: " ++ show genClassifier)+ $ counterexample ("size: " ++ show (classifierSize genClassifier))+ $ classifierSize genClassifier <= 100
+ tests/Test/RecoverRTTI/Show.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE NumericUnderscores #-}++-- | Verify that 'anythingToString' produces same result as 'show'+module Test.RecoverRTTI.Show (tests) where++import Test.Tasty+import Test.Tasty.QuickCheck hiding (classify)++import Debug.RecoverRTTI+import Debug.RecoverRTTI.Util++import Test.RecoverRTTI.Arbitrary ()+import Test.RecoverRTTI.ConcreteClassifier++tests :: TestTree+tests = testGroup "Test.RecoverRTTI.Show" [+ testProperty "showGenerated" prop_showGenerated+ , testProperty "anythingToString" prop_anythingToString+ ]++-- | Check that the generated value is showable+--+-- This is a sanity check on the generator.+prop_showGenerated :: Some Value -> Property+prop_showGenerated (Some (Value _cc x)) =+ counterexample ("length: " ++ show (length (show x)))+ $ property (length (show x) < 1_000_000)++-- | Compare " normal " 'show' against the " recovered " 'show'+prop_anythingToString :: Some Value -> Property+prop_anythingToString (Some (Value _cc x)) =+ counterexample ("inferred: " ++ show (classify x))+ $ within 1_000_000+ $ show x === anythingToString x
+ tests/Test/RecoverRTTI/Staged.hs view
@@ -0,0 +1,340 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-}++-- | Staged inference+--+-- Suppose we have a user-defined type such as+--+-- > data T a = MkT a+--+-- When we classify a value of type @T a@, 'classify' will give us "one level"+-- type inference only: it will classify this value as+--+-- > UserDefined (Constr "pkg" "modl" "MkT")+--+-- It will not attempt to classify the /arguments/ to the constructor. If we+-- /know/ which user-defined types we're interested in, however, we can do+-- full classification by doing "staged inference", repeatedly calling+-- 'classify' at every level.+--+-- In this module we do staged inference for the user-defined types used in the+-- test suite. The primary purpose of this is to provide evidence that+-- 'classify' gives us enough information to do so.+module Test.RecoverRTTI.Staged (+ Reclassified(..)+ , reclassify+ , classifyThenReclassify+ ) where++import Control.Monad.Except+import Data.Bifunctor+import Data.Kind+import Data.Map (Map)+import Data.Set (Set)+import Data.SOP hiding (NS(..))+import Data.Typeable+import Data.Void+import GHC.Exts (Any)+import GHC.Real+import GHC.TypeLits++import qualified Data.Map as Map+import qualified Data.Set as Set++import Debug.RecoverRTTI+import Debug.RecoverRTTI.Util+import Debug.RecoverRTTI.Util.TypeLevel++import Test.RecoverRTTI.ConcreteClassifier+import Test.RecoverRTTI.UserDefined++{-------------------------------------------------------------------------------+ Reclassified values+-------------------------------------------------------------------------------}++-- | Reclassified values+--+-- We cannot go directly from a @Classifier a@ to a @ConcreteClassifier a@:+-- in the case of a user-defined type, @a@ will be of the form+--+-- > UserDefined c+--+-- for some @c@, but we want to return classifier for a specific type, maybe+--+-- > NonRecursive Char+--+-- Therefore instead we return a classifier for some other type @b@, but along+-- with a proof that we can /coerce/ from @a@ to @b@.+data Reclassified a where+ Reclassified :: ConcreteClassifier b -> (a -> b) -> Reclassified a++-- | Classify, then reclassify+classifyThenReclassify :: a -> Except String (Reclassified a)+classifyThenReclassify x =+ case classified x of+ Left closure ->+ throwError $ "Failed to classify closure " ++ show closure+ Right classifier ->+ reclassify classifier++-- | Reclassify values+--+-- See detailed description in 'Reclassified'.+reclassify :: Classified a -> Except String (Reclassified a)+reclassify = go+ where+ go :: Classified a -> Except String (Reclassified a)+ go (Classified c x) = case c of+ -- Primitive types++ C_Bool -> return $ Reclassified CC_Bool id+ C_Char -> return $ Reclassified CC_Char id+ C_Double -> return $ Reclassified CC_Double id+ C_Float -> return $ Reclassified CC_Float id+ C_Int -> return $ Reclassified CC_Int id+ C_Int8 -> return $ Reclassified CC_Int8 id+ C_Int16 -> return $ Reclassified CC_Int16 id+ C_Int32 -> return $ Reclassified CC_Int32 id+ C_Int64 -> return $ Reclassified CC_Int64 id+ C_Integer -> return $ Reclassified CC_Integer id+ C_Ordering -> return $ Reclassified CC_Ordering id+ C_Unit -> return $ Reclassified CC_Unit id+ C_Word -> return $ Reclassified CC_Word id+ C_Word8 -> return $ Reclassified CC_Word8 id+ C_Word16 -> return $ Reclassified CC_Word16 id+ C_Word32 -> return $ Reclassified CC_Word32 id+ C_Word64 -> return $ Reclassified CC_Word64 id++ -- String types++ C_String -> return $ Reclassified CC_String id+ C_BS_Strict -> return $ Reclassified CC_BS_Strict id+ C_BS_Lazy -> return $ Reclassified CC_BS_Lazy id+ C_BS_Short -> return $ Reclassified CC_BS_Short id+ C_Text_Strict -> return $ Reclassified CC_Text_Strict id+ C_Text_Lazy -> return $ Reclassified CC_Text_Lazy id++ -- Aeson++ C_Value -> return $ Reclassified CC_Value id++ -- Compound++ C_Maybe c' -> goMaybeF fmap CC_Maybe c'+ C_Either c' -> goEitherF bimap CC_Either c'+ C_List c' -> goMaybeF fmap CC_List c'+ C_Ratio c' -> goF coerceRatio CC_Ratio c'+ C_Set c' -> goMaybeF coerceSet CC_Set c'+ C_Map c' -> goMaybePairF coerceMap CC_Map c'+ C_IntSet -> return $ Reclassified CC_IntSet id+ C_IntMap c' -> goMaybeF fmap CC_IntMap c'+ C_Sequence c' -> goMaybeF fmap CC_Sequence c'+ C_Tree c' -> goF fmap CC_Tree c'++ C_Tuple (Classifiers cs) ->+ reclassifyTuple <$> (hsequence' (hmap (Comp . reclassify) cs))++ -- Reference cells++ C_STRef -> return $ Reclassified CC_STRef id+ C_TVar -> return $ Reclassified CC_TVar id+ C_MVar -> return $ Reclassified CC_MVar id++ -- Functions++ C_Fun -> return $ Reclassified CC_Fun id++ -- User-defined++ C_Custom s ->+ firstMatch ("Unknown constructor: " ++ prettyKnownConstr s) [+ reclassifyF CC_User_NonRec s x+ , reclassifyF CC_User_Rec s x+ , reclassifyF CC_User_Unlifted s x+ ]++ goMaybeF :: forall f a.+ (forall x x'. (x -> x') -> f x -> f x')+ -> (forall x. MaybeF ConcreteClassifier x -> ConcreteClassifier (f x))+ -> MaybeF Classified a+ -> Except String (Reclassified (f a))+ goMaybeF _ cc FNothing =+ return $ Reclassified (cc FNothing) id+ goMaybeF coerce cc (FJust x') =+ aux <$> reclassify x'+ where+ aux :: Reclassified x -> Reclassified (f x)+ aux (Reclassified c_x f_x) =+ Reclassified (cc (FJust c_x)) (coerce f_x)++ goEitherF :: forall f a b.+ (forall x x' y y'. (x -> x') -> (y -> y') -> f x y -> f x' y')+ -> (forall x y. EitherF ConcreteClassifier x y -> ConcreteClassifier (f x y))+ -> EitherF Classified a b+ -> Except String (Reclassified (f a b))+ goEitherF coerce cc (FLeft x') =+ aux <$> reclassify x'+ where+ aux :: Reclassified x -> Reclassified (f x Void)+ aux (Reclassified c_x f_x) =+ Reclassified (cc (FLeft c_x)) (coerce f_x id)+ goEitherF coerce cc (FRight y') =+ aux <$> reclassify y'+ where+ aux :: Reclassified y -> Reclassified (f Void y)+ aux (Reclassified c_y f_y) =+ Reclassified (cc (FRight c_y)) (coerce id f_y)++ goMaybePairF :: forall f a b.+ (forall x x' y y'. (x -> x') -> (y -> y') -> f x y -> f x' y')+ -> (forall x y. MaybePairF ConcreteClassifier x y -> ConcreteClassifier (f x y))+ -> MaybePairF Classified a b+ -> Except String (Reclassified (f a b))+ goMaybePairF _ cc FNothingPair =+ return $ Reclassified (cc FNothingPair) id+ goMaybePairF coerce cc (FJustPair x' y') =+ aux <$> reclassify x' <*> reclassify y'+ where+ aux :: Reclassified x -> Reclassified y -> Reclassified (f x y)+ aux (Reclassified c_x f_x) (Reclassified c_y f_y) =+ Reclassified (cc (FJustPair c_x c_y)) (coerce f_x f_y)++ goF :: forall f a.+ (forall x x'. (x -> x') -> f x -> f x')+ -> (forall x. ConcreteClassifier x -> ConcreteClassifier (f x))+ -> Classified a+ -> Except String (Reclassified (f a))+ goF coerce cc x' =+ aux <$> reclassify x'+ where+ aux :: Reclassified x -> Reclassified (f x)+ aux (Reclassified c_x f_x) =+ Reclassified (cc c_x) (coerce f_x)++reclassifyTuple ::+ (SListI xs, IsValidSize (Length xs))+ => NP Reclassified xs -> Reclassified (WrappedTuple xs)+reclassifyTuple = \cs ->+ go cs $ \cs' f ->+ Reclassified (CC_Tuple (ConcreteClassifiers cs')) f+ where+ go :: forall xs r.+ (SListI xs, IsValidSize (Length xs))+ => NP Reclassified xs+ -> (forall ys.+ (SListI ys, Length ys ~ Length xs)+ => NP ConcreteClassifier ys+ -> (WrappedTuple xs -> WrappedTuple ys)+ -> r+ )+ -> r+ go Nil k = k Nil id+ go (x :* xs) k = smallerIsValid (Proxy @(Length xs)) $+ go xs $ \np f_np ->+ case x of+ Reclassified y f_y ->+ k (y :* np) (bimapTuple f_y f_np)++{-------------------------------------------------------------------------------+ Lift coercions to non-functor types+-------------------------------------------------------------------------------}++coerceRatio :: (x -> x') -> Ratio x -> Ratio x'+coerceRatio f (x :% y) = f x :% f y++coerceSet :: (x -> x') -> Set x -> Set x'+coerceSet f = Set.fromDistinctAscList . map f . Set.toAscList++coerceMap :: (x -> x') -> (y -> y') -> Map x y -> Map x' y'+coerceMap f g = Map.fromDistinctAscList . map (bimap f g) . Map.toAscList++{-------------------------------------------------------------------------------+ When we reclassify values of user-defined types with type arguments, we need+ to know that if @c@ is a value of, say, @T a@, it is also a value of @T b@,+ for all @b@. This is what enables staged inference: we know it's a constructor+ of @T x@ for /some/ @x@, and then as a second step figure out what @x@ is.+-------------------------------------------------------------------------------}++data ConstrOfF f c a = ConstrOfF (IsConstrOf (f a) c)++unsafeCoerceF :: Poly (ConstrOfF f c) -> UserDefined c -> f a+unsafeCoerceF (Poly (ConstrOfF isConstrOf)) = aux isConstrOf+ where+ aux :: forall a c. IsConstrOf a c -> UserDefined c -> a+ aux IsConstrOf = unsafeCoerceUserDefined++checkConstrOfF ::+ forall f c. (+ Phantom (ConstrOfF f c)+ , SingI (Constrs (f Any))+ )+ => Sing c -> Maybe (Poly (ConstrOfF f c))+checkConstrOfF c = maybePoly (ConstrOfF <$> checkIsConstrOf @(f Any) c)++reclassifyF ::+ forall (f :: Type -> Type) (c :: Constr Symbol). (+ Phantom (ConstrOfF f c)+ , SingI (Constrs (f Any))+ , Traversable f+ , Typeable f+ )+ => (forall a. MaybeF ConcreteClassifier a -> ConcreteClassifier (f a))+ -> Sing (c :: Constr Symbol)+ -> UserDefined c+ -> Except String (Maybe (Reclassified (UserDefined c)))+reclassifyF cc = \c x ->+ case checkConstrOfF @f c of+ Nothing ->+ return Nothing+ Just constrOfF ->+ case checkEmptyTraversable (unsafeCoerceF constrOfF x) of+ Right _ ->+ return . Just $ Reclassified (cc FNothing) (unsafeCoerceF constrOfF)+ Left x' -> do+ Just . aux constrOfF <$> classifyThenReclassify x'+ where+ aux :: Poly (ConstrOfF f c)+ -> Reclassified a -- Classification of the elements+ -> Reclassified (UserDefined c) -- Classification of the container+ aux constrOfF (Reclassified c f) =+ Reclassified (cc (FJust c)) (fmap f . unsafeCoerceF constrOfF)++{-------------------------------------------------------------------------------+ Prove that the functors of our user-defined types are indeed parametric++ NOTE: It's kinda frustrating that we have to repeat this for every type.+ That's non-trivial to fix though; a polymorphic function would need as+ quantified constraint that++ > forall a b. Constrs (f a) ~ Constrs (f b)++ but that is not legal Haskell: we cannot use type synonyms in quantified+ constraints (frustratingly and unnecessarily).+-------------------------------------------------------------------------------}++instance Phantom (ConstrOfF NonRecursive c) where+ phantom (ConstrOfF IsConstrOf) = ConstrOfF IsConstrOf++instance Phantom (ConstrOfF Recursive c) where+ phantom (ConstrOfF IsConstrOf) = ConstrOfF IsConstrOf++instance Phantom (ConstrOfF ContainsUnlifted c) where+ phantom (ConstrOfF IsConstrOf) = ConstrOfF IsConstrOf++{-------------------------------------------------------------------------------+ Auxiliary+-------------------------------------------------------------------------------}++firstMatch :: forall e a. e -> [Except e (Maybe a)] -> Except e a+firstMatch err = go+ where+ go :: [Except e (Maybe a)] -> Except e a+ go [] = throwError err+ go (x:xs) = x >>= maybe (go xs) return
+ tests/Test/RecoverRTTI/UserDefined.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UnboxedTuples #-}++-- | Just some examples of user-defined types+module Test.RecoverRTTI.UserDefined (+ NonRecursive(..)+ , Recursive(..)+ , recursiveFromList+ , ContainsUnlifted -- opaque+ , exampleContainsUnlifted+ ) where++import GHC.Generics+import GHC.IO+import GHC.Prim++{-------------------------------------------------------------------------------+ User-defined datatypes+-------------------------------------------------------------------------------}++-- | Example of a non-recursive user-defined type+data NonRecursive a = NR1 Int | NR2 a Bool+ deriving (Show, Eq, Generic, Functor, Foldable, Traversable)++-- | Example of a recursive user-defined type+data Recursive a = RNil | RCons a (Recursive a)+ deriving (Show, Eq, Generic, Functor, Foldable, Traversable)++recursiveFromList :: [a] -> Recursive a+recursiveFromList = foldr RCons RNil++{-------------------------------------------------------------------------------+ Example of a type with an unlifted value++ Most instances here don't really make much sense; this is just here to+ verify we don't crash when coming across unlifted values+-------------------------------------------------------------------------------}++-- | Example of a user-defined type containing something unlifted+data ContainsUnlifted a = NothingHere | ContainsUnlifted (MutableArray# RealWorld Int) a+ deriving (Functor, Foldable, Traversable)++-- We can't derive a Generic instance, we must produce just enough info so that+-- we can do the right type casts+instance Generic (ContainsUnlifted a) where+ type Rep (ContainsUnlifted a) = Rep_ContainsUnlifted++ from = error "'from' not defined for ContainsUnlifted"+ to = error "'to' not defined for ContainsUnlifted"++-- We don't bother specifiying the arguments to the constructors+type Rep_ContainsUnlifted =+ M1 D ('MetaData "ContainsUnlifted" "Test.RecoverRTTI.UserDefined" "main" 'False)+ ( M1 C ('MetaCons "NothingHere" 'PrefixI 'False) U1+ :+:+ M1 C ('MetaCons "ContainsUnlifted" 'PrefixI 'False) U1+ )++instance Show a => Show (ContainsUnlifted a) where+ showsPrec _ NothingHere =+ showString "NothingHere"+ showsPrec p (ContainsUnlifted _ x) = showParen (p >= 11) $+ showString "ContainsUnlifted "+ . showsPrec 11 x++instance Eq (ContainsUnlifted a) where+ _ == _ = True++exampleContainsUnlifted :: ContainsUnlifted ()+{-# NOINLINE exampleContainsUnlifted #-}+exampleContainsUnlifted = unsafePerformIO $ IO $ \world ->+ let !(# world', arr #) = newArray# 5# 0 world+ in (# world', ContainsUnlifted arr () #)