{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, ExistentialQuantification, Rank2Types #-}
{-# OPTIONS_GHC -Wno-orphans #-}

{- |
    /DEPRECATED/: Use "Data.Generics.Uniplate.Data" instead.

    This module exports 'Biplate' instances for everything with 'Data' defined.
    Using GHC the 'Data' instances can be constructed with @deriving Data@.
-}
module Data.Generics.PlateData
    {-# DEPRECATED "Use Data.Generics.Uniplate.Data instead" #-}
    (
    module Data.Generics.Biplate
    ) where

import Data.Generics.Biplate
import Data.Generics.Uniplate.Internal.Utils
import Data.Generics


data Box find = Box {forall find. Box find -> forall a. Typeable a => a -> Answer find
fromBox :: forall a . Typeable a => a -> Answer find}

data Answer a = Hit {forall a. Answer a -> a
_fromHit :: a} -- you just hit the element you were after (here is a cast)
              | Follow -- go forward, you will find something
              | Miss -- you failed to sink my battleship!



containsMatch :: (Data start, Typeable start, Data find, Typeable find) =>
                 start -> find ->
                 Box find

-- GHC 6.4.2 does not export typeRepKey, so we can't do the trick
-- as efficiently, so we just give up and revert to always following

containsMatch :: forall start find.
(Data start, Typeable start, Data find, Typeable find) =>
start -> find -> Box find
containsMatch start
start find
find = forall find. (forall a. Typeable a => a -> Answer find) -> Box find
Box forall {a} {a}. (Typeable a, Typeable a) => a -> Answer a
query
    where
        query :: a -> Answer a
query a
a = case forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
a of
                       Just a
y -> forall a. a -> Answer a
Hit a
y
                       Maybe a
Nothing -> forall a. Answer a
Follow


instance (Data a, Typeable a) => Uniplate a where
    uniplate :: UniplateType a
uniplate = forall on with.
(Data on, Data with, Typeable on, Typeable with) =>
(forall a. Typeable a => a -> Answer with) -> on -> CC with on
collect_generate (forall find. Box find -> forall a. Typeable a => a -> Answer find
fromBox Box a
answer)
        where
            answer :: Box a
            answer :: Box a
answer = forall start find.
(Data start, Typeable start, Data find, Typeable find) =>
start -> find -> Box find
containsMatch (forall a. HasCallStack => a
undefined :: a) (forall a. HasCallStack => a
undefined :: a)


instance (Data a, Data b, Uniplate b, Typeable a, Typeable b) => Biplate a b where
    biplate :: BiplateType a b
biplate = forall on with.
(Data on, Data with, Typeable on, Typeable with) =>
(forall a. Typeable a => a -> Answer with) -> on -> CC with on
collect_generate_self (forall find. Box find -> forall a. Typeable a => a -> Answer find
fromBox Box b
answer)
        where
            answer :: Box b
            answer :: Box b
answer = forall start find.
(Data start, Typeable start, Data find, Typeable find) =>
start -> find -> Box find
containsMatch (forall a. HasCallStack => a
undefined :: a) (forall a. HasCallStack => a
undefined :: b)


newtype C x a = C {forall x a. C x a -> CC x a
fromC :: CC x a}

type CC x a = (Str x, Str x -> a)


collect_generate_self :: (Data on, Data with, Typeable on, Typeable with) =>
                         (forall a . Typeable a => a -> Answer with) -> on -> CC with on
collect_generate_self :: forall on with.
(Data on, Data with, Typeable on, Typeable with) =>
(forall a. Typeable a => a -> Answer with) -> on -> CC with on
collect_generate_self forall a. Typeable a => a -> Answer with
oracle on
x = (Str with, Str with -> on)
res
        where
            res :: (Str with, Str with -> on)
res = case forall a. Typeable a => a -> Answer with
oracle on
x of
                       Hit with
y -> (forall a. a -> Str a
One with
y, \(One with
x) -> forall a b. a -> b
unsafeCoerce with
x)
                       Answer with
Follow -> forall on with.
(Data on, Data with, Typeable on, Typeable with) =>
(forall a. Typeable a => a -> Answer with) -> on -> CC with on
collect_generate forall a. Typeable a => a -> Answer with
oracle on
x
                       Answer with
Miss -> (forall a. Str a
Zero, \Str with
_ -> on
x)


collect_generate :: (Data on, Data with, Typeable on, Typeable with) =>
                    (forall a . Typeable a => a -> Answer with) -> on -> CC with on
collect_generate :: forall on with.
(Data on, Data with, Typeable on, Typeable with) =>
(forall a. Typeable a => a -> Answer with) -> on -> CC with on
collect_generate forall a. Typeable a => a -> Answer with
oracle on
item = forall x a. C x a -> CC x a
fromC forall a b. (a -> b) -> a -> b
$ forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> a -> c a
gfoldl forall {t} {a}. Data t => C with (t -> a) -> t -> C with a
combine forall {a} {x}. a -> C x a
create on
item
    where
        -- forall a b . Data a => C with (a -> b) -> a -> C with b
        combine :: C with (t -> a) -> t -> C with a
combine (C (Str with
c,Str with -> t -> a
g)) t
x = case forall on with.
(Data on, Data with, Typeable on, Typeable with) =>
(forall a. Typeable a => a -> Answer with) -> on -> CC with on
collect_generate_self forall a. Typeable a => a -> Answer with
oracle t
x of
                                  (Str with
c2, Str with -> t
g2) -> forall x a. CC x a -> C x a
C (forall a. Str a -> Str a -> Str a
Two Str with
c Str with
c2, \(Two Str with
c' Str with
c2') -> Str with -> t -> a
g Str with
c' (Str with -> t
g2 Str with
c2'))

        -- forall g . g -> C with g
        create :: a -> C x a
create a
x = forall x a. CC x a -> C x a
C (forall a. Str a
Zero, \Str x
_ -> a
x)