Reader monad, implicit parameters, or something else altogether?

All, I have a growing amount of astrodynamics code that relies on various physical "constants". The problem with these so called "constants" are that they either aren't really constants or aren't well known. An example is the leap second table (see Data.Time.Clock.TAI). I'd like to be able to fetch current values of these constants at runtime and make them accessible to my astrodynamics functions by some means. To clarify, once initialized the constants will be considered constant for the remainder of the program. I'd store the constants in a data structure along the lines of:
data AstroData a = AstroData { mu_Earth :: GravitationalParameter a , leapSeconds :: LeapSecondTable }
I would like to know if there is any consensus on what is the best way to make such a data structure accessible in pure functions. Passing it explicitly would be a mess. It seems that two options are to use either a Reader monad or implicit parameters. Using a Reader monad is straight forward enough though it requires writing/converting code in/to monadic style and adds some clutter to the formulae. It seems implicit parameters could be cleaner but I've seen them referred to as everything from evil to "just what you need" and rendering the Reader monad obsolete... What do you people recommend? Thanks, Bjorn Buckwalter

G'day all.
Quoting Bjorn Buckwalter
I'd store the constants in a data structure along the lines of:
data AstroData a = AstroData { mu_Earth :: GravitationalParameter a , leapSeconds :: LeapSecondTable }
I would like to know if there is any consensus on what is the best way to make such a data structure accessible in pure functions. Passing it explicitly would be a mess.
In this situation, there isn't necessarily any shame in using a top-level unsafePerformIO as long as it's well-hidden: module AstroData (AstroData(..), globalAstroData) where data AstroData = AstroData Int -- You really don't want this function inlined. You also -- really don't want this function to be polymorphic. {-# NOINLINE globalAstroData #-} globalAstroData :: AstroData globalAstroData = unsafePerformIO $ do d <- return 42 -- Or whatever return (AstroData d) Cheers, Andrew Bromage

Just an idiot-level question: so these "constants" are subject to revision, but *how often*? What is the actual cost of recompiling and using them *as* constants, compared with the cost of rereading the stuff every time you run the program and passing it around? -- If stupidity were a crime, who'd 'scape hanging?

G'day all.
Quoting "Richard A. O'Keefe"
Just an idiot-level question: so these "constants" are subject to revision, but *how often*?
Good question. For leap seconds: - The data can change no quicker than once every 6 months. - The shortest time between changes was 6 months, and the longest (so far) was 7 years. - The mean change is once every 18 months. - You get just under 6 months' notice before a change comes into effect. (No more, no less.) For most programs, it's the last point that concerns me the most...
What is the actual cost of recompiling and using them *as* constants, compared with the cost of rereading the stuff every time you run the program and passing it around?
...because the main cost probably isn't recompiling, it's redeployment. I don't know about this program in particular, but release cycles longer than six months are hardly uncommon in our business. Cheers, Andrew Bromage

Richard A. O'Keefe
Just an idiot-level question: so these "constants" are subject to revision, but *how often*? What is the actual cost of recompiling and using them *as* constants, compared with the cost of rereading the stuff every time you run the program and passing it around?
My apologies but I kind of lost track of this thread after the initial helpful replies and didn't follow up diligently on what went only to haskell-cafe (which I don't follow regularly) and not to my inbox. In case you are still curious an example of data that changes frequently is Earth orientation parameters (of which the leap seconds which Andrew elaborated on are one). These include e.g. the difference between UT1 and UTC (UT1-UTC) which is necessary to accurately relate the position and orientation of e.g. a ground based observer to an object in inertial space. UT1-UTC is continuously monitored with new observed an predicted values being published daily. Additional parameters and their update frequencies are listed at [1] and available compiled and with some documentation at [2]. [1] http://www.celestrak.com/SpaceData/EOP-format.asp [2] http://www.celestrak.com/SpaceData/ A piece of software precessing e.g. satellite orbit observations would ideally use the latest Earth orientation parameter data without requiring a recompile for each day. Thanks, Bjorn

On Mon, 18 Aug 2008, ajb@spamcop.net wrote:
G'day all.
Quoting Bjorn Buckwalter
: I'd store the constants in a data structure along the lines of:
data AstroData a = AstroData { mu_Earth :: GravitationalParameter a , leapSeconds :: LeapSecondTable }
I would like to know if there is any consensus on what is the best way to make such a data structure accessible in pure functions. Passing it explicitly would be a mess.
In this situation, there isn't necessarily any shame in using a top-level unsafePerformIO as long as it's well-hidden:
module AstroData (AstroData(..), globalAstroData) where
data AstroData = AstroData Int
But here my argument about playing around with the Planck constant becomes relevant.

On Wed, Aug 20, 2008 at 1:49 AM, Henning Thielemann
On Mon, 18 Aug 2008, ajb@spamcop.net wrote:
G'day all.
Quoting Bjorn Buckwalter
: I'd store the constants in a data structure along the lines of:
data AstroData a = AstroData { mu_Earth :: GravitationalParameter a , leapSeconds :: LeapSecondTable }
I would like to know if there is any consensus on what is the best way to make such a data structure accessible in pure functions. Passing it explicitly would be a mess.
In this situation, there isn't necessarily any shame in using a top-level unsafePerformIO as long as it's well-hidden:
module AstroData (AstroData(..), globalAstroData) where
data AstroData = AstroData Int
But here my argument about playing around with the Planck constant becomes relevant. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
You can always change how you unsafePerformIO the data, though. If you want to set Planck's constant to 42 (or whatever), just change the unsafePerformIO $ <whatever> to unsafePerformIO $ return 42. Alex

On Fri, 22 Aug 2008, Alexander Dunlap wrote:
You can always change how you unsafePerformIO the data, though. If you want to set Planck's constant to 42 (or whatever), just change the unsafePerformIO $ <whatever> to unsafePerformIO $ return 42.
you can't change it at runtime
participants (5)
-
ajb@spamcop.net
-
Alexander Dunlap
-
Bjorn Buckwalter
-
Henning Thielemann
-
Richard A. O'Keefe