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

On Mon, 18 Aug 2008, Bjorn Buckwalter wrote:
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...
I expect that you will get the same range of opinions as you got from your search. As far as I know implicit parameters break referential transparency. http://www.haskell.org/haskellwiki/The_Monad.Reader/Issue2/FunWithLinearImpl... So I prefer Reader monad. The burden of converting to monadic style pays off when you need to use the same code with different values for the "constants". (E.g. find out for which value of the Planck constant the universe collapses and for which it oscillates etc. :-)

On Mon, Aug 18, 2008 at 11:16 AM, Henning Thielemann
On Mon, 18 Aug 2008, Bjorn Buckwalter wrote:
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...
I expect that you will get the same range of opinions as you got from your search. As far as I know implicit parameters break referential transparency. http://www.haskell.org/haskellwiki/The_Monad.Reader/Issue2/FunWithLinearImpl... So I prefer Reader monad. The burden of converting to monadic style pays off when you need to use the same code with different values for the "constants". (E.g. find out for which value of the Planck constant the universe collapses and for which it oscillates etc. :-)
Love the example but could you elaborate a little on how monadic style helps with this? (This is probably a matter of it not being obvious to me what approach you would take to solving the problem.) By the way, can anyone comment on implicit parameters interacting with monadic code? If I were to use implicit parameters and later realize that I need other monadic functionality, e.g. Writer, would I be in a tough spot or would the implicit parameters continue to work "seemlesly" in the monadic code? Thanks, Bjorn Buckwalter

On Mon, 18 Aug 2008, Bjorn Buckwalter wrote:
On Mon, Aug 18, 2008 at 11:16 AM, Henning Thielemann
wrote: On Mon, 18 Aug 2008, Bjorn Buckwalter wrote:
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...
I expect that you will get the same range of opinions as you got from your search. As far as I know implicit parameters break referential transparency. http://www.haskell.org/haskellwiki/The_Monad.Reader/Issue2/FunWithLinearImpl... So I prefer Reader monad. The burden of converting to monadic style pays off when you need to use the same code with different values for the "constants". (E.g. find out for which value of the Planck constant the universe collapses and for which it oscillates etc. :-)
Love the example but could you elaborate a little on how monadic style helps with this? (This is probably a matter of it not being obvious to me what approach you would take to solving the problem.)
Instead of muEarth :: GravitationalParameter a muEarth = ??? escapeVelocity :: a escapeVelocity = ... muEarth ... you would write data AstroData a = AstroData { muEarth :: GravitationalParameter a , leapSeconds :: LeapSecondTable } escapeVelocity :: Reader (AstroData a) a escapeVelocity = do mu <- asks muEarth return (... mu ...) Even better you would introduce a newtype for Reader (AstroData a). This way you can add any monadic functionality later (Writer et.al.).

On 2008 Aug 18, at 11:16, Henning Thielemann wrote:
know implicit parameters break referential transparency. http://www.haskell.org/haskellwiki/The_Monad.Reader/Issue2/FunWithLinearImpl...
Are you making the same mistake I did? Linear implicit parameters are different from implicit parameters. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Mon, 18 Aug 2008, Brandon S. Allbery KF8NH wrote:
On 2008 Aug 18, at 11:16, Henning Thielemann wrote:
know implicit parameters break referential transparency. http://www.haskell.org/haskellwiki/The_Monad.Reader/Issue2/FunWithLinearImpl...
Are you making the same mistake I did? Linear implicit parameters are different from implicit parameters.
I haven't look into the details, so I certainly make any possible mistake.

On 2008 Aug 18, at 10:59, Bjorn Buckwalter wrote:
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?
Last time I ran into this, I needed a Reader for other reasons so just reused it. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Bjorn Buckwalter wrote:
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?
I'd go for applicative functors :) instance Applicative ((->) Constants) where pure = const f <*> x = \r -> (f r) (x r) This way, you don't have to use do-syntax and can keep an applicative look-and-feel. mu = \AstroData{mu_Earth} -> mu_Earth example = pure (*) <*> pure 5 <*> mu Lifting arithmetic operations and numbers will get annoying with the time, but that's nothing an instance Num can't solve. (If it can't, just hide (*) and (+) from the prelude and define your own.) Regards, apfelmus
participants (4)
-
apfelmus
-
Bjorn Buckwalter
-
Brandon S. Allbery KF8NH
-
Henning Thielemann