Strafunski-ATermLib (empty) → 1.6
raw patch · 8 files changed
+667/−0 lines, 8 filesdep +basedep +containerssetup-changed
Dependencies added: base, containers
Files
- Data/ATerm/AbstractSyntax.hs +27/−0
- Data/ATerm/Conversion.hs +131/−0
- Data/ATerm/IO.hs +120/−0
- Data/ATerm/Lib.hs +31/−0
- Data/ATerm/ReadWrite.hs +320/−0
- LICENSE +1/−0
- Setup.hs +2/−0
- Strafunski-ATermLib.cabal +35/−0
+ Data/ATerm/AbstractSyntax.hs view
@@ -0,0 +1,27 @@+-----------------------------------------------------------------------------+-- |+-- Copyright : (c) Joost Visser 2004+-- License : LGPL+-- +-- Maintainer : joost.visser@di.uminho.pt+-- Stability : experimental+-- Portability : portable+--+-- This module is part of the ATerm library for Haskell. It defines+-- the abstract syntax of ATerms as a Haskell datatype.+--+-----------------------------------------------------------------------------++module Data.ATerm.AbstractSyntax (+ ATerm(..)+) where++-----------------------------------------------------------------------------++-- | The abstract syntax of ATerms.+data ATerm = AAppl String [ATerm] -- ^ Application+ | AList [ATerm] -- ^ Lists+ | AInt Integer -- ^ Integers+ deriving (Read,Show,Eq,Ord)++------------------------------------------------------------------------------
+ Data/ATerm/Conversion.hs view
@@ -0,0 +1,131 @@+-----------------------------------------------------------------------------+-- |+-- Copyright : (c) Joost Visser 2004+-- License : LGPL+-- +-- Maintainer : joost.visser@di.uminho.pt+-- Stability : experimental+-- Portability : portable+--+-- This module is part of the ATerm library for Haskell. It provides the class+-- ATermConvertible of types that are convertible to and from ATerms. Additionally,+-- it provides default instances of this class for some predefined Prelude+-- types.+--+-----------------------------------------------------------------------------++module Data.ATerm.Conversion where++import Data.ATerm.AbstractSyntax+import Data.ATerm.ReadWrite+import Data.Ratio+import Data.Char++-----------------------------------------------------------------------------+-- * Conversion to and from ATerms++class ATermConvertible t where+ -- | Convert to an ATerm.+ toATerm :: t -> ATerm+ -- | Convert from an ATerm.+ fromATerm :: ATerm -> t ++-- | Auxiliary function for reporting errors.+fromATermError :: String -> ATerm -> a+fromATermError t u + = error ("Cannot convert ATerm to "++t++": "++(err u))+ where err u = case u of + AAppl s _ -> '!':s+ AList _ -> "!AList"+ otherwise -> "!AInt"+ +-----------------------------------------------------------------------------+-- * Conversion of ATerms to and from Strings++-- | Convert to a textual ATerm representation without sharing (TXT format).+toATermString :: ATermConvertible t => t -> String+toATermString t = writeATerm (toATerm t)++-- | Convert to a textual ATerm representation with full sharing (TAF format).+toSharedATermString :: ATermConvertible t => t -> String+toSharedATermString t = writeSharedATerm (toATerm t)++-- | Convert from a textual ATerm representation.+fromATermString :: ATermConvertible t => String -> t+fromATermString s = fromATerm (readATerm s)++-----------------------------------------------------------------------------+-- * Instances for basic types+ -- Lists+instance ATermConvertible a => ATermConvertible [a] where+ toATerm as = AList (map toATerm as)+ fromATerm (AList as) = map fromATerm as+ fromATerm t = fromATermError "Prelude.[]" t++ -- Maybe+instance ATermConvertible a => ATermConvertible (Maybe a) where+ toATerm Nothing = AAppl "None" []+ toATerm (Just a) = AAppl "Just" [toATerm a]+ fromATerm (AAppl "None" []) = Nothing+ fromATerm (AAppl "Some" [a]) = Just (fromATerm a)+ fromATerm t = fromATermError "Prelude.Maybe" t+ + -- 2-Tuples+instance (ATermConvertible a, ATermConvertible b) + => ATermConvertible (a,b) where+ toATerm (a,b) = AAppl "Tuple2" [toATerm a, toATerm b]+ fromATerm (AAppl "Tuple2" [a,b]) = (fromATerm a,fromATerm b)+ fromATerm t = fromATermError "Prelude.(,)" t+ + -- Either+instance (ATermConvertible a, ATermConvertible b) + => ATermConvertible (Either a b) where+ toATerm (Left a) = AAppl "Left" [toATerm a]+ toATerm (Right b) = AAppl "Right" [toATerm b]+ fromATerm (AAppl "Left" [a]) = Left (fromATerm a)+ fromATerm (AAppl "Right" [b]) = Right (fromATerm b)+ fromATerm t = fromATermError "Prelude.Either" t+ + -- String+instance ATermConvertible String where+ toATerm s = AAppl (show s) []+ fromATerm (AAppl s []) = read s+ fromATerm t = fromATermError "Prelude.String" t++ -- Integral+instance Integral n => ATermConvertible n where+ toATerm i = AInt (toInteger i)+ fromATerm (AInt i) = fromInteger i+ fromATerm t = fromATermError "Prelude.Integral" t++ -- Bool+instance ATermConvertible Bool where+ toATerm True = AAppl "True" []+ toATerm False = AAppl "False" []+ fromATerm (AAppl "True" []) = True+ fromATerm (AAppl "False" []) = False+ fromATerm t = fromATermError "Prelude.Bool" t+ -- Bool++instance ATermConvertible () where+ toATerm () = AAppl "()" []+ fromATerm (AAppl "()" []) = ()+ fromATerm t = fromATermError "Prelude.()" t++ -- Char+instance ATermConvertible Char where+ toATerm c = AInt (toInteger . ord $ c)+ fromATerm (AInt c) = chr . fromInteger $ c+ fromATerm t = fromATermError "Prelude.Char" t++ -- Ratio+instance (Integral a, ATermConvertible a) + => ATermConvertible (Ratio a) where+ toATerm xy = AAppl "Ratio" [toATerm (numerator xy), + toATerm (denominator xy)]+ fromATerm (AAppl "Ratio" [x,y])+ = (fromATerm x)%(fromATerm y)+ fromATerm t = fromATermError "Ratio.Ratio" t+ +------------------------------------------------------------------------------+
+ Data/ATerm/IO.hs view
@@ -0,0 +1,120 @@+-----------------------------------------------------------------------------+-- |+-- Copyright : (c) Joost Visser 2004+-- License : LGPL+-- +-- Maintainer : joost.visser@di.uminho.pt+-- Stability : experimental+-- Portability : portable+--+-- This module is part of the ATerm library for Haskell. This module+-- provides wrapper functions that take care of IO.+--+-----------------------------------------------------------------------------++module Data.ATerm.IO where++import System.IO+import System.Environment ( getArgs )+import Data.ATerm.AbstractSyntax+import Data.ATerm.Conversion +import Data.ATerm.ReadWrite+import Data.Char++-----------------------------------------------------------------------------+-- * Transformation wrapper+ +-- | Wrapper function to create a main function in the IO monad, given a+-- program name and a monadic transformation function.+atermIOwrap :: (ATermConvertible t, ATermConvertible a) + => ProgramName -> (t -> IO a) -> IO ()+atermIOwrap progName mtransform+ = do args <- getArgs+ opts <- return $ parseOptions progName args+ sin <- readStream (fin opts)+ tin <- return . fromATerm . dehyphenAST . readATerm $ sin+ tout <- mtransform $ tin+ sout <- return . toString (format opts) $ tout+ writeStream (fout opts) sout + where+ readStream "#stdin#" = getContents+ readStream f = readFile f+ writeStream "#stdout#" = putStr+ writeStream f = writeFile f+ toString format + = case format of + "TEXT" -> toATermString+ "TAF" -> toSharedATermString+ _ -> error $ "format unknown: "++"\n"++usage progName + +-----------------------------------------------------------------------------+-- * Helpers++type ProgramName = String++-- | Turn hyphens in a String into underscores.+dehyphen :: String -> String+dehyphen str+ = map aux str+ where aux '-' = '_'+ aux c = c++-- | Turn hyphens in AST into underscores except inside nodes+-- that represent literals.+dehyphenAST :: ATerm -> ATerm+--dehyphenAST t@(AAppl "Sdf_Literal" ts) = t+dehyphenAST (AAppl f ts) = AAppl (dehyphenUnquoted f) (map dehyphenAST ts)+dehyphenAST (AList ts) = AList (map dehyphenAST ts)+dehyphenAST t = t++-- | Turn hyphens in unquoted literal into underscores.+dehyphenUnquoted s@('\"':_) = s+dehyphenUnquoted s = dehyphen s++-- | Turn the first character into upper case. +headToUpper :: String -> String+headToUpper [] = []+headToUpper (c:cs) = (toUpper c):cs++-- | Make all AFun's start with an uppercase letter.+afunCap :: ATerm -> ATerm+afunCap (AAppl afun ts) = AAppl (headToUpper afun) (map afunCap ts)+afunCap (AList ts) = AList (map afunCap ts)+afunCap t = t++-----------------------------------------------------------------------------+-- * Option handling ++data OptionsATermIO+ = OptionsATermIO { fin :: String, fout :: String, format :: String }++defaultOptionsATermIO :: OptionsATermIO+defaultOptionsATermIO+ = OptionsATermIO { fin = "#stdin#", fout = "#stdout#", format = "TEXT" }+ +parseOptions :: String -> [String] -> OptionsATermIO+parseOptions programName args+ = p args+ where + p [] = defaultOptionsATermIO+ p ("-t":args) = (p args){ format = "TEXT" }+ p ("-s":args) = (p args){ format = "TAF" }+ p ("-b":args) = err "BAF format not supported!"+ p ("-i":fname:args) = (p args){ fin = fname }+ p ("-o":fname:args) = (p args){ fout = fname }+ p args = err $ "Can't parse options: "++concat args+ err msg = error $ msg++"\n"++usage programName++usage :: String -> String+usage programName+ = unlines ["Usage","",+ " "++programName++" [-i <fname>] [-o <fname>] [-t|-s]",+ "",+ "Options","",+ " -i <fname> name of input file (default: stdin)",+ " -o <fname> name of output file (default: stdout)",+ " -t output format is TEXT (plain text)",+ " -s output format is TAF (textual sharing)"+ ] + +-------------------------------------------------------------------------------
+ Data/ATerm/Lib.hs view
@@ -0,0 +1,31 @@+-----------------------------------------------------------------------------+-- |+-- Copyright : (c) Joost Visser 2004+-- License : LGPL+-- +-- Maintainer : joost.visser@di.uminho.pt+-- Stability : experimental+-- Portability : portable+--+-- This module is part of the ATerm library for Haskell. This +-- is the top module of the library. Most users only need to +-- import this module.+--+-----------------------------------------------------------------------------++module Data.ATerm.Lib (++ module Data.ATerm.AbstractSyntax,+ module Data.ATerm.ReadWrite,+ module Data.ATerm.Conversion,+ module Data.ATerm.Lib,+ module Data.ATerm.IO++) where++import Data.ATerm.AbstractSyntax+import Data.ATerm.ReadWrite+import Data.ATerm.Conversion+import Data.ATerm.IO++-------------------------------------------------------------------------------
+ Data/ATerm/ReadWrite.hs view
@@ -0,0 +1,320 @@+-----------------------------------------------------------------------------+-- |+-- Copyright : (c) Joost Visser 2004+-- License : LGPL+-- +-- Maintainer : joost.visser@di.uminho.pt+-- Stability : experimental+-- Portability : portable+--+-- This module is part of the ATerm library for Haskell. It contains functions+-- for reading and writing ATerms from and to Strings. Two ATerm formats are+-- supported:+--+-- * AT: plain (non-shared) textual ATerms+-- +-- * TAF: shared textual ATerms+--+-- The binary ATerm format (BAF) is not supported.+--+-- Current limitations:+--+-- * BLOBS and place-holders are not supported.+-- +-- * Annotations are not supported.+--+-----------------------------------------------------------------------------++module Data.ATerm.ReadWrite (+ readATerm,+ writeATerm,+ writeSharedATerm+) where++import Data.ATerm.AbstractSyntax+import Data.Map as FM+import Data.Char++-----------------------------------------------------------------------------+-- * From String to ATerm++-- | Parse the given string into an ATerm.+readATerm :: String -> ATerm+readATerm ('!':str) = let (t,_,_,_) = readTAF str emptyRT 0 in t+readATerm str = let (t,_) = readAT str in t++ -- non-shared --++readAT ('[':str) = let (kids, str') = readATs (dropSpaces str)+ in (AList kids, str')+readAT str@(c:cs)+ | isIntHead c = let (i,str') = span isDigit cs+ in (AInt (read (c:i)),str')+ | otherwise = let (c,str') = readAFun str+ (kids, str'') = readParenATs (dropSpaces str')+ in (AAppl c kids, str'')++readAFun ('"':str) = let (c,('"':str')) = spanNotQuote' str + in (quote c,str')+readAFun str = spanAFunChar str++readParenATs ('(':str) = readATs (dropSpaces str)+readParenATs str = ([],str)+++readATs (')':str) = ([],str)+readATs (']':str) = ([],str)+readATs str = readATs1 str++readATs1 str = let (t,str') = readAT (dropSpaces str)+ (ts,str'') = readATs' (dropSpaces str')+ in (t:ts,str'')++readATs' (',':str) = readATs1 (dropSpaces str)+readATs' (')':str) = ([],str)+readATs' (']':str) = ([],str)++ -- shared --+ +readTAF :: String -> ReadTable -> Int+ -> (ATerm,String,ReadTable,Int)+readTAF ('#':str) tbl l = let (i,str') = spanAbbrevChar str+ in (getElementRT (deAbbrev i) tbl, + str',tbl,l+(length i)+1) +readTAF ('[':str) tbl l = let (kids, str',tbl',l') + = readTAFs (dropSpaces str) tbl 1+ t = AList kids+ in (t, str',condAddElementRT t l' tbl',l+l')+readTAF str@(c:cs) tbl l+ | isIntHead c = let (i,str') = span isDigit cs+ ci = (c:i)+ l' = length ci+ t = AInt (read ci) + tbl' = condAddElementRT t l' tbl+ in (t,str',tbl',l+l')+ | otherwise = let (c,str') = readAFun str+ (kids, str'',tbl',l') + = readParenTAFs (dropSpaces str') tbl 0+ t = AAppl c kids+ lks = if Prelude.null kids then 0 else l'+ l'' = (length c) + lks+ in (t, str'',condAddElementRT t l'' tbl',l'')++readParenTAFs ('(':str) tbl l = readTAFs (dropSpaces str) tbl l+readParenTAFs str tbl l = ([],str,tbl,l)++readTAFs (')':str) tbl l = ([],str,tbl,l+1)+readTAFs (']':str) tbl l = ([],str,tbl,l+1)+readTAFs str tbl l = readTAFs1 str tbl l++readTAFs1 str tbl l = let (t,str',tbl',l')+ = readTAF (dropSpaces str) tbl l+ (ts,str'',tbl'',l'') + = readTAFs' (dropSpaces str') tbl' l'+ in (t:ts,str'',tbl'',l'')++readTAFs' (',':str) tbl l = readTAFs1 (dropSpaces str) tbl (l+1)+readTAFs' (')':str) tbl l = ([],str,tbl,l+1)+readTAFs' (']':str) tbl l = ([],str,tbl,l+1)++ -- helpers --++dropSpaces = dropWhile isSpace+spanAFunChar = span isAFunChar+isAFunChar c = (isAlphaNum c) || (c `elem` "-_*+")+spanNotQuote = span (/='"')+spanAbbrevChar = span (`elem` toBase64)+isIntHead c = (isDigit c) || (c=='-')+quote str = ('"':str)++"\""++spanNotQuote' [] = ([],[])+spanNotQuote' xs@('"':xs') = ([],xs)+spanNotQuote' xs@('\\':'"':xs') = ('\\':'"':ys,zs) + where (ys,zs) = spanNotQuote' xs'+spanNotQuote' xs@('\\':'\\':xs')= ('\\':'\\':ys,zs) + where (ys,zs) = spanNotQuote' xs'+spanNotQuote' xs@(x:xs') = (x:ys,zs) + where (ys,zs) = spanNotQuote' xs'++-----------------------------------------------------------------------------+-- * From ATerm to String ++-- | Write the given ATerm to non-shared textual representation (TXT format).+writeATerm :: ATerm -> String+writeATerm t = writeAT t++-- | Write the given ATerm to fully shared textual representation (TAF format).+writeSharedATerm :: ATerm -> String+writeSharedATerm t = let (s,_) = writeTAF t emptyWT in ('!':s)++ -- non-shared --++writeAT :: ATerm -> String+writeAT (AAppl c ts) = writeATermAux c (Prelude.map writeAT ts)+writeAT (AList ts) = bracket (commaSep (Prelude.map writeAT ts))+writeAT (AInt i) = show i++ -- shared --++writeTAF :: ATerm -> WriteTable -> (String,WriteTable)+writeTAF t tbl = case getIndexWT t tbl of+ (Just i) -> (makeAbbrev i,tbl) + Nothing -> (str, condAddElementWT t str tbl')+ where (str,tbl') = writeTAF' t tbl++writeTAF' (AAppl c ts) tbl = let (kids,tbl') = writeTAFs ts tbl+ in (writeATermAux c kids,tbl')+writeTAF' (AList ts) tbl = let (kids,tbl') = writeTAFs ts tbl+ in (bracket (commaSep kids),tbl')+writeTAF' (AInt i) tbl = (show i,tbl)++writeTAFs [] tbl = ([],tbl)+writeTAFs (t:ts) tbl = let (str,tbl') = writeTAF t tbl+ (strs,tbl'') = writeTAFs ts tbl'+ in ((str:strs),tbl'')++ -- helpers --+ +writeATermAux c [] = c+writeATermAux c ts = c++(parenthesise (commaSep ts))++sepBy sep (x:y:ys) = x:sep:sepBy sep (y:ys)+sepBy sep ys = ys++commaSep strs = concat (sepBy "," strs)+bracket str = "["++str++"]"+parenthesise str = "("++str++")"++-----------------------------------------------------------------------------+-- * Tables of ATerms ++ -- For reading (remove sharing)+-- Using reversed List+type ReadTable = (Integer,[ATerm])+emptyRT = (0,[])+-- Hook to prevent expansion of productions. This is useful when reading+-- huge AsFix files. +getElementRT' i tbl = case getElementRT i tbl of+ (AAppl "prod" _) -> AAppl "#prod" []+ t -> t+getElementRT i tbl = (snd tbl)!!!((fst tbl)-i-1)+addElementRT a tbl = ((fst tbl)+1,a:(snd tbl))+sizeOfRT tbl = fst tbl+{--- Using Finite Map+type ReadTable = FiniteMap Integer ATerm+emptyRT = emptyFM+getElementRT i tbl = lookupWithDefaultFM tbl (error "getElement") i+addElementRT a tbl = addToFM tbl (sizeOfRT tbl) a+sizeOfRT tbl = toInteger (sizeFM tbl)+-}+{--- Using some imported Edison sequence+type ReadTable = T.Seq ATerm+emptyRT = T.empty :: ReadTable+getElementRT i tbl = T.lookup tbl (toInt i)+addElementRT t tbl = T.snoc tbl t+sizeOfRT tbl = T.size tbl+-}++condAddElementRT t l tbl+ = if (length next_abbrev) < l then+ addElementRT t tbl+ else+ tbl+ --where next_abbrev = makeAbbrev (toInteger (sizeOfRT tbl)+1)+ where next_abbrev = makeAbbrev (toInteger (sizeOfRT tbl))+ +condAddElementRT' t str tbl+ = if (length next_abbrev) < (length str) then+ addElementRT t tbl+ else+ tbl+ where next_abbrev = makeAbbrev (toInteger (sizeOfRT tbl)+1)+ + -- For writing (create sharing)+-- Using FiniteMap+type WriteTable = FM.Map ATerm Integer+emptyWT = FM.empty+getIndexWT a tbl = FM.lookup a tbl+addElementWT a tbl = FM.insert a (sizeOfWT tbl) tbl+sizeOfWT tbl = toInteger (FM.size tbl)++condAddElementWT t str tbl+ = if (length next_abbrev) < (length str) then+ addElementWT t tbl+ else+ tbl+ --where next_abbrev = makeAbbrev (toInteger (sizeOfWT tbl)+1)+ where next_abbrev = makeAbbrev (toInteger (sizeOfWT tbl))++-----------------------------------------------------------------------------+-- * Base 64 encoding++mkAbbrev x+ | x == 0 = [toBase64!!0]+ | otherwise = reverse (mkAbbrevAux x)++mkAbbrevAux x+ | x == 0 = []+ | x > 0 = (toBase64!!!m:mkAbbrevAux d) where (d,m) = divMod x 64++deAbbrev x = deAbbrevAux (reverse x)++deAbbrevAux [] = 0+deAbbrevAux (c:cs) = let (Just i) = indexOf c toBase64+ r = deAbbrevAux cs+ in (i + 64*r)++toBase64 =+ [ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' + ]+ +makeAbbrev i = '#':mkAbbrev i++-----------------------------------------------------------------------------+-- * Helpers ++indexOf t [] = Nothing+indexOf t (x:xs) = if t==x+ then (Just (0::Integer))+ else case indexOf t xs of+ (Just i) -> Just (i+1)+ Nothing -> Nothing+(!!!) :: [b] -> Integer -> b+(x:_) !!! 0 = x+(_:xs) !!! n | n>0 = xs !!! (n-1)+(_:_) !!! _ = error "!!!: negative index"+[] !!! _ = error "!!!: index too large"++-----------------------------------------------------------------------------+-- * Future work++{- The code could be made more readable by introducing+ special monads that hide the consumed String/ATerm and the + table that is built during reading/writing+ +newtype ReadMonad t = RM { runRM :: String -> ReadTable + -> (t,String,ReadTable) }+instance Monad ReadMonad where+ return t = RM $ \str tbl -> (t,str,tbl)+ rm >>= f = RM $ \str tbl -> let (t,str',tbl') = runRM rm str tbl+ in runRM (f t) str' tbl'+ + I guess this should be a combined ParserMonad and StateMonad. +-}++-------------------------------------------------------------------------------+-- * Testing++-- | Test whether reading and writing to and from shared aterm representations+-- (TAF format) deals correctly with the bounderies of the base-64 encoding.+testAbbrevBoundaries :: Bool+testAbbrevBoundaries + = writeSharedATerm term == shared && readATerm shared == term+ where+ term = AList $ Prelude.map AInt ([100..164]++[100..164])+ shared = "![100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,#A,#B,#C,#D,#E,#F,#G,#H,#I,#J,#K,#L,#M,#N,#O,#P,#Q,#R,#S,#T,#U,#V,#W,#X,#Y,#Z,#a,#b,#c,#d,#e,#f,#g,#h,#i,#j,#k,#l,#m,#n,#o,#p,#q,#r,#s,#t,#u,#v,#w,#x,#y,#z,#0,#1,#2,#3,#4,#5,#6,#7,#8,#9,#+,#/,164]"++-------------------------------------------------------------------------------
+ LICENSE view
@@ -0,0 +1,1 @@+Does not exist.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Strafunski-ATermLib.cabal view
@@ -0,0 +1,35 @@+-- Initial ATermLib.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++name: Strafunski-ATermLib+version: 1.6+synopsis: An abstract data type designed for the exchange of tree-like data structures+description: Library for dealing with ATerms (annotated terms) in Haskell. See https://github.com/cwi-swat/aterms for more information on ATerms.+license: BSD3+license-file: LICENSE+author: Ralf Laemmel, Joost Visser+maintainer: darmanithird@gmail.com+category: Data+build-type: Simple+cabal-version: >=1.8+source-repository head+ type: git+ location: https://github.com/jkoppel/Strafunski-ATermLib++library++ Extensions:+ TypeSynonymInstances,+ FlexibleInstances,+ UndecidableInstances,+ OverlappingInstances++++ exposed-modules: Data.ATerm.AbstractSyntax,+ Data.ATerm.Conversion,+ Data.ATerm.IO,+ Data.ATerm.Lib,+ Data.ATerm.ReadWrite+ -- other-modules: + build-depends: base ==4.5.*, containers ==0.4.*