packages feed

adaptive-containers-0.2.1: scripts/derive-list-pair.hs

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# OPTIONS -fglasgow-exts #-}

module AdaptiveDerive where

import Data.Generics
import Data.List
import Text.PrettyPrint
import Control.Monad

import Data.Int
import Data.Word

{-

instance Adapt Int Int where

  data Pair Int Int = PIntInt {-# UNPACK #-}!Int {-# UNPACK #-}!Int

  fst (PIntInt a _) = a
  snd (PIntInt _ b) = b
  curry f x y    =  f (PIntInt x y)
  uncurry f p    =  f (fst p) (snd p)

 -}

------------------------------------------------------------------------

main = sequence_  . intersperse (putStrLn "") $
    [ deriveM t u
    | Box t <- types
    , Box u <- types ]

data Box = forall a. (Typeable a, Data a) => Box a

types :: [Box]
types = [ Box (undefined :: Int)
        , Box (undefined :: Integer)
        , Box (undefined :: Int8)
        , Box (undefined :: Int16)
        , Box (undefined :: Int32)
        , Box (undefined :: Int64)
        , Box (undefined :: Word)
        , Box (undefined :: Word8)
        , Box (undefined :: Word16)
        , Box (undefined :: Word32)
        , Box (undefined :: Word64)
        , Box (undefined :: Double)
        , Box (undefined :: Float)
        , Box (undefined :: Char)
        ]

------------------------------------------------------------------------

deriveM :: forall a b . (Typeable a, Data a, Typeable b, Data b) => a -> b -> IO ()
deriveM (a :: a) (b :: b) = putStrLn $ derive (undefined :: a) (undefined :: b)

{-
-- Monomorphic, but we have to flatten ourselves. GHC is doing something wrong.
instance AdaptList (Pair Int Int) where
    data List (Pair Int Int)
        = EmptyPairIntInt
        | ConsPairIntInt {-# UNPACK #-}!Int {-# UNPACK #-}!Int (List (Pair Int Int))

    empty                = EmptyPairIntInt
    cons x xs            = ConsPairIntInt (fst x) (snd x) xs

    null EmptyPairIntInt = True
    null _               = False

    head EmptyPairIntInt         = errorEmptyList "head"
    head (ConsPairIntInt x y _)  = pair x y
    tail EmptyPairIntInt         = errorEmptyList "tail"
    tail (ConsPairIntInt _ _ xs) = xs
-}



derive :: (Typeable a, Data a, Typeable b, Data b) => a  -> b -> String
derive x y = render $
   hang
    (hsep [text "instance", text "AdaptList",
                 parens (text "Pair" <+> text type_x <+> text type_y), text "where"])
    4
    (vcat [
        --    data List (Pair Int Int)
        --       = EmptyPairIntInt
        --       | ConsPairIntInt {-# UNPACK #-}!Int {-# UNPACK #-}!Int (List (Pair Int Int))

        hsep [ text "data"
             ,      text "List"
             ,      parens (hsep [text "Pair"
                                 ,      text type_x
                                 ,      text type_y
                                 ])
             ],

        (hang empty 4
           (vcat [ hsep [ char '=', text myemptyconstr]
                 , hsep [ char '|'
                        ,   text myconsconstr
                        ,   text "{-# UNPACK #-}!" <> text type_x
                        ,   text "{-# UNPACK #-}!" <> text type_y
                        , parens (text "List" <+>
                              parens (text "Pair" <+> text type_x <+> text type_y))
                        ]
                 ]))

       ,hsep [  text "empty"
             ,char '='
             ,  text myemptyconstr]

        --     cons x xs            = ConsPairIntInt (fst x) (snd x) xs

       ,hsep [  text "cons"
             ,    char 'x'
             ,    char 'z'
             ,char '='
             ,  text myconsconstr
             ,  parens (text "fst" <+> char 'x')
             ,  parens (text "snd" <+> char 'x')
            ,   char 'z'
             ]

       ,hsep [  text "null"
             ,  text myemptyconstr
             ,char '='
             ,  text "True"]
       ,hsep [  text "null"
             ,  char '_'
             ,char '='
             ,  text "False"]

       ,hsep [  text "head"
             ,  text myemptyconstr
             ,char '='
             ,  text "errorEmptyList \"head\""
             ]
       ,hsep [  text "head"
             ,  parens (text myconsconstr <+> char 'x' <+> char 'y' <+> char '_')
             ,char '='
             ,  text "pair" <+> char 'x' <+> char 'y']

       ,hsep [  text "tail"
             ,  text myemptyconstr
             ,char '='
             ,  text "errorEmptyList \"tail\""
             ]
       ,hsep [  text "tail"
             ,  parens (text myconsconstr <+> char '_' <+> char '_' <+> char 'x')
             ,char '='
             ,  char 'x']

          ])

{-

-}

 where
    type_x = inst_a

    type_y = inst_b

    myemptyconstr = "EmptyPair" ++ type_x ++ type_y
    myconsconstr = "ConsPair" ++ type_x ++ type_y

    inst_a = wrap $ tyConString typeName ++ concatMap (" "++) typeLetters
        where (typeName,typeChildren) = splitTyConApp (typeOf x)
              typeLetters = take nTypeChildren manyLetters
              nTypeChildren = length typeChildren
              wrap x = if nTypeChildren > 0 then "("++x++")" else x

    inst_b = wrap $ tyConString typeName ++ concatMap (" "++) typeLetters
        where (typeName,typeChildren) = splitTyConApp (typeOf y)
              typeLetters = take nTypeChildren manyLetters
              nTypeChildren = length typeChildren
              wrap x = if nTypeChildren > 0 then "("++x++")" else x

    manyLetters = map (:[]) ['a'..'z']