-- | -- Module : Data.Express.Name -- Copyright : (c) 2019-2020 Rudy Matela -- License : 3-Clause BSD (see the file LICENSE) -- Maintainer : Rudy Matela -- -- Defines the 'Name' type class. module Data.Express.Name ( Name (..) , names , variableNamesFromTemplate ) where import Data.Express.Utils.String import Data.Char import Data.List import Data.Ratio (Ratio) import Data.Word (Word) -- for GHC <= 7.8 -- | -- If we were to come up with a variable name for the given type -- what 'name' would it be? -- -- An instance for a given type @ Ty @ is simply given by: -- -- > instance Name Ty where name _ = "x" -- -- Examples: -- -- > > name (undefined :: Int) -- > "x" -- -- > > name (undefined :: Bool) -- > "p" -- -- > > name (undefined :: [Int]) -- > "xs" -- -- This is then used to generate an infinite list of variable 'names': -- -- > > names (undefined :: Int) -- > ["x", "y", "z", "x'", "y'", "z'", "x''", "y''", "z''", ...] -- -- > > names (undefined :: Bool) -- > ["p", "q", "r", "p'", "q'", "r'", "p''", "q''", "r''", ...] -- -- > > names (undefined :: [Int]) -- > ["xs", "ys", "zs", "xs'", "ys'", "zs'", "xs''", "ys''", ...] class Name a where -- | /O(1)./ -- -- Returns a name for a variable of the given argument's type. -- -- > > name (undefined :: Int) -- > "x" -- -- > > name (undefined :: [Bool]) -- > "ps" -- -- > > name (undefined :: [Maybe Integer]) -- > "mxs" -- -- The default definition is: -- -- > name _ = "x" name :: a -> String name _ = "x" -- | -- > name (undefined :: ()) = "u" -- > names (undefined :: ()) = ["u", "v", "w", "u'", "v'", ...] instance Name () where name _ = "u" -- | -- > name (undefined :: Bool) = "p" -- > names (undefined :: Bool) = ["p", "q", "r", "p'", "q'", ...] instance Name Bool where name _ = "p" -- | -- > name (undefined :: Int) = "x" -- > names (undefined :: Int) = ["x", "y", "z", "x'", "y'", ...] instance Name Int where name _ = "x" -- | -- > name (undefined :: Integer) = "x" -- > names (undefined :: Integer) = ["x", "y", "z", "x'", ...] instance Name Integer where name _ = "x" -- | -- > name (undefined :: Char) = "c" -- > names (undefined :: Char) = ["c", "d", "e", "c'", "d'", ...] instance Name Char where name _ = "c" -- | -- > name (undefined :: Ordering) = "o" -- > names (undefined :: Ordering) = ["o", "p", "q", "o'", ...] instance Name Ordering where name _ = "o" -- | -- > name (undefined :: Rational) = "q" -- > names (undefined :: Rational) = ["q", "r", "s", "q'", ...] instance Name (Ratio a) where name _ = "q" -- | -- > name (undefined :: Float) = "x" -- > names (undefined :: Float) = ["x", "y", "z", "x'", ...] instance Name Float where name _ = "x" -- | -- > name (undefined :: Double) = "x" -- > names (undefined :: Double) = ["x", "y", "z", "x'", ...] instance Name Double where name _ = "x" -- | -- > names (undefined :: ()->()) = ["f", "g", "h", "f'", ...] -- > names (undefined :: Int->Int) = ["f", "g", "h", ...] instance Name (a -> b) where name _ = "f" -- | -- > names (undefined :: Maybe Int) = ["mx", "mx1", "mx2", ...] -- > nemes (undefined :: Maybe Bool) = ["mp", "mp1", "mp2", ...] instance Name a => Name (Maybe a) where name mx = "m" ++ name x where Just x = mx -- | -- > names (undefined :: Either Int Int) = ["exy", "exy1", ...] -- > names (undefined :: Either Int Bool) = ["exp", "exp1", ...] instance (Name a, Name b) => Name (Either a b) where name exy = "e" ++ n ++ m where Left x = exy Right y = exy n = name x m = head $ names y \\ [n] -- | -- > names (undefined :: (Int,Int)) = ["xy", "zw", "xy'", ...] -- > names (undefined :: (Bool,Bool)) = ["pq", "rs", "pq'", ...] instance (Name a, Name b) => Name (a,b) where name xy = n ++ m where (x,y) = xy n = name x m = head $ names y \\ [n] -- | -- > names (undefined :: (Int,Int,Int)) = ["xyz","uvw", ...] -- > names (undefined :: (Int,Bool,Char)) = ["xpc", "xpc1", ...] instance (Name a, Name b, Name c) => Name (a,b,c) where name xyz = n ++ m ++ o where (x,y,z) = xyz n = name x m = head $ names y \\ [n] o = head $ names z \\ [n,m] -- | -- > names (undefined :: ((),(),(),())) = ["uuuu", "uuuu1", ...] -- > names (undefined :: (Int,Int,Int,Int)) = ["xxxx", ...] instance (Name a, Name b, Name c, Name d) => Name (a,b,c,d) where name xyzw = name x ++ name y ++ name z ++ name w where (x,y,z,w) = xyzw -- | -- > names (undefined :: [Int]) = ["xs", "ys", "zs", "xs'", ...] -- > names (undefined :: [Bool]) = ["ps", "qs", "rs", "ps'", ...] instance Name a => Name [a] where name xs = name (head xs) ++ "s" -- | -- Returns na infinite list of variable names from the given type: -- the result of 'variableNamesFromTemplate' after 'name'. -- -- > > names (undefined :: Int) -- > ["x", "y", "z", "x'", "y'", "z'", "x''", "y''", "z''", ...] -- -- > > names (undefined :: Bool) -- > ["p", "q", "r", "p'", "q'", "r'", "p''", "q''", "r''", ...] -- -- > > names (undefined :: [Int]) -- > ["xs", "ys", "zs", "xs'", "ys'", "zs'", "xs''", "ys''", ...] names :: Name a => a -> [String] names = variableNamesFromTemplate . name -- instances of further types and arities -- instance Name Word where name _ = "x" instance (Name a, Name b, Name c, Name d, Name e) => Name (a,b,c,d,e) where name xyzwv = name x ++ name y ++ name z ++ name w ++ name v where (x,y,z,w,v) = xyzwv instance (Name a, Name b, Name c, Name d, Name e, Name f) => Name (a,b,c,d,e,f) where name xyzwvu = name x ++ name y ++ name z ++ name w ++ name v ++ name u where (x,y,z,w,v,u) = xyzwvu instance (Name a, Name b, Name c, Name d, Name e, Name f, Name g) => Name (a,b,c,d,e,f,g) where name xyzwvut = name x ++ name y ++ name z ++ name w ++ name v ++ name u ++ name t where (x,y,z,w,v,u,t) = xyzwvut instance (Name a, Name b, Name c, Name d, Name e, Name f, Name g, Name h) => Name (a,b,c,d,e,f,g,h) where name xyzwvuts = name x ++ name y ++ name z ++ name w ++ name v ++ name u ++ name t ++ name s where (x,y,z,w,v,u,t,s) = xyzwvuts instance ( Name a, Name b, Name c, Name d , Name e, Name f, Name g, Name h , Name i) => Name (a,b,c,d,e,f,g,h,i) where name xyzwvutsr = name x ++ name y ++ name z ++ name w ++ name v ++ name u ++ name t ++ name s ++ name r where (x,y,z,w,v,u,t,s,r) = xyzwvutsr instance ( Name a, Name b, Name c, Name d , Name e, Name f, Name g, Name h , Name i, Name j ) => Name (a,b,c,d,e,f,g,h,i,j) where name xyzwvutsrq = name x ++ name y ++ name z ++ name w ++ name v ++ name u ++ name t ++ name s ++ name r ++ name q where (x,y,z,w,v,u,t,s,r,q) = xyzwvutsrq instance ( Name a, Name b, Name c, Name d , Name e, Name f, Name g, Name h , Name i, Name j, Name k ) => Name (a,b,c,d,e,f,g,h,i,j,k) where name xyzwvutsrqp = name x ++ name y ++ name z ++ name w ++ name v ++ name u ++ name t ++ name s ++ name r ++ name q ++ name p where (x,y,z,w,v,u,t,s,r,q,p) = xyzwvutsrqp instance ( Name a, Name b, Name c, Name d , Name e, Name f, Name g, Name h , Name i, Name j, Name k, Name l ) => Name (a,b,c,d,e,f,g,h,i,j,k,l) where name xyzwvutsrqpo = name x ++ name y ++ name z ++ name w ++ name v ++ name u ++ name t ++ name s ++ name r ++ name q ++ name p ++ name o where (x,y,z,w,v,u,t,s,r,q,p,o) = xyzwvutsrqpo