packages feed

adaptive-containers-0.3: scripts/derive-maybe.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 | Box t <- 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 . (Typeable a, Data a) => a -> IO ()
deriveM (a :: a) = putStrLn $ derive (undefined :: a)

{-
instance AdaptList Int where
    data List Int = EmptyInt | ConsInt {-# UNPACK #-}!Int (List Int)

    empty               = EmptyInt
    cons x xs           = ConsInt x xs
    null EmptyInt       = True
    null _              = False
    head EmptyInt       = errorEmptyList "head"
    head (ConsInt x _)  = x
    tail EmptyInt       = errorEmptyList "tail"
    tail (ConsInt _ xs) = xs
-}

derive :: (Typeable a, Data a) => a  -> String
derive x = render $

   hang
    (hsep [text "instance", text "AdaptMaybe", text type_x, text "where"])
    4
    (vcat [
        hsep [ text "data"
             ,      text "Maybe"
             ,      text type_x
             , char '='
             ,      text myNothingConstr
             , char '|'
             ,      text myJustConstr
             ,      text "{-# UNPACK #-}!" <> text type_x
             ]

{-
maybe n _ NothingInt  = n
maybe _ f (JustInt x) = f x
-}

       ,hsep [  text "just"
             ,char '='
             ,  text myJustConstr]

       ,hsep [  text "nothing"
             ,char '='
             ,  text myNothingConstr]

       ,hsep [  text "isJust"
             ,  parens (text myJustConstr <+> char '_' )
             ,char '='
             ,  text "True"]
       ,hsep [  text "isJust"
             ,  char '_'
             ,char '='
             ,  text "False"]

       ,hsep [  text "maybe"
             ,  char 'n'
             ,  char '_'
             ,  text myNothingConstr
             ,char '='
             ,  char 'n'
             ]
       ,hsep [  text "maybe"
             ,  char '_'
             ,  char 'f'
             ,  parens (text myJustConstr <+> char 'x')
             ,char '='
             ,  char 'f'
             ,  char 'x']

        ])


 where
    type_x = inst_a

    myNothingConstr = "Nothing" ++ type_x
    myJustConstr = "Just" ++ type_x

    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

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