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,
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") WriteModelet outputstring = calculationsFrom (varValue v)
Though it would more succinct to use pattern matching:
hPutStr outh outputstring
hClose outh
writeFileFor :: Named a -> IO ()
writeFileFor (Named name value) =
do
outh <- openFile (name ++ ".txt") WriteMode
let outputstring = calculationsFrom value
As a side issue - having access to variables rather than values seems
hPutStr outh outputstring
hClose outh
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