
This is what I have in my library. I use it every now and then, when I need
sth with a name. Of course you still have to implement the name function for
that data type, but I've no better way of doing it.
class Show a => HasName a where
-- | accessor method for name
name :: a -> String
-- | a method the update the stored name
updateName :: String -> a -> a
-- | show functions (for this type-class) are assumed to be shown
*without* the name
-- | if you want to show with the name, you must use this function
instead of show
-- | default implementation should be almost always sufficient.
showWithName :: a -> String
-- | prints instead of just showing.
-- | default implementation should be almost always sufficient.
printWithName :: a -> IO()
-- | if "name" is not implemented, just return a notice
name x = "don't know my name: " ++ show x
-- | if "updateName" is not implemented, there is nothing to do but
giving an error
updateName n x = error ("updateName(" ++ n ++ ") not implemented: " ++
show x)
showWithName p = name p ++ ": " ++ show p
printWithName = putStrLn . showWithName
Hope it helps,
On 20 March 2010 10:09, Stephen Tetley
Hi John
I can't see there is a way of getting the name of a variable.
A Haskell compiler like GHC is fairly free to do what it likes with /values/, so a variable doesn't necessarily exist in a tangible form in a program - i.e. it might get compiled away due to constant folding[*]:
main = let x = 5 in do { print (10 * x) }
... would likely become:
main = do { print (10 * 5) } -- by constant folding
... and finally
main = do { print 50 } -- by static expression elimination
--
Values not /variables/ - are more tangible. Provided the type of the value is an instance of the type class Data, you can get at least the value's type name and its constructor name.
To get something like named variable you would have to make a data type with two fields one for a name label and one for the value, e.g. :
data Named a = Named String a deriving (Show)
valName :: Named a -> String valName (Name s _) = s
valValue :: Named a -> a valValue (Name _ a) = a
When you use a variable you want associated with a name, you will have to be a bit pedantic about always supplying the same name to construct it:
e.g.: if you have a constant called scale_factor
scale_factor :: Named Int scale_factor = Named "scale_factor" 10
[At an advanced level you could probably use Template Haskell to make this easier]
--
Your program would then be something like :
writeFileFor :: Named a -> IO () writeFileFor v = do let nameOfV = valName v outh <- openFile (nameOfV ++ ".txt") WriteMode
let outputstring = calculationsFrom (varValue v)
hPutStr outh outputstring
hClose outh
Though it would more succinct to use pattern matching:
writeFileFor :: Named a -> IO () writeFileFor (Named name value) = do outh <- openFile (name ++ ".txt") WriteMode
let outputstring = calculationsFrom value
hPutStr outh outputstring
hClose outh
As a side issue - having access to variables rather than values seems an usually prospect for any programming language. I'd guess that it would effectively prevent the language being compiled or the language would would have to limit reflective / introspective access only to global variables.
Best wishes
Stephen
[*] Actually for important reasons GHC does not do that much constant folding - but it is possibly the easiest optimization to use as an illustration here. _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
-- Ozgur Akgun