packages feed

activehs-0.2: Specialize.hs

{-# LANGUAGE FlexibleInstances #-}
module Specialize 
    ( specialize
    ) where

import Data.List
import Data.Function

import Language.Haskell.Exts.Parser
import Language.Haskell.Exts.Pretty
import Language.Haskell.Exts.Syntax
import Language.Haskell.Exts.Extension

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

specialize :: String -> Either String (String, String)
specialize a
    = case parseTypeWithMode (defaultParseMode {extensions = [FlexibleContexts], fixities = []}) a of
        ParseFailed loc s -> Left $ show s
        ParseOk t -> let

                (t',t'') = convert (split t)

            in Right (prettyPrint t', prettyPrint t'')

split :: Type -> ([(String, [String])], Type)
split (TyForall Nothing l t) 
    = ( map (\x -> (fst (head x), map snd x)) $ groupBy ((==) `on` fst) $ sort
          [(v,s) | ClassA (UnQual (Ident s)) [TyVar (Ident v)]<-l]
      , t
      )
split t 
    = ([], t)

convert :: ([(String, [String])], Type) -> (Type, Type)
convert (m, t) = (app True mm t, app False mm t)  where mm = map resolve m

app :: Bool -> [(String, [[Char]])] -> Type -> Type
app b m t = f t where
    f (TyFun a b) = TyFun (f a) (f b)
    f (TyTuple bo l) = TyTuple bo $ map f l
    f (TyList t) = TyList (f t)
    f (TyParen t) = TyParen (f t)
    f (TyApp x t) = TyApp (f x) (f t)
    f (TyVar (Ident s)) = mkV $ head $ [y | (v,x)<-m, v==s, y<-ff  x] ++ ff allT
    f t = t

    ff = if b then id else reverse

mkV :: String -> Type
mkV v = TyVar $ Ident v

resolve :: (String, [String]) -> (String, [String])
resolve (v, l) = (v, foldl1 intersect $ map res l)

allT :: [String]
allT = ["Double","Integer","Char","Bool","()"]

res :: String -> [String]
res x | x `elem` ["RealFrac", "Real", "RealFloat", "Floating", "Fractional"] = ["Double"]
res x | x `elem` ["Num"] = ["Double","Integer"]
res x | x `elem` ["Integral"] = ["Integer"]
res x | x `elem` ["Monad"] = ["[]","Maybe"]
res x | x `elem` ["Ord","Show","Eq","Enum"] = allT
res x = []  -- !!!