1
votes

I recently created a Config record type which contains data/functions which are used throughout my application. For example, let's say it's

data Config m u = Config
    { issuer       :: Text
    , loadUser     :: LoadUser m u
    , authenticate :: Authenticate m
    }

and I have another function which actually creates the application from the configuration:

buildServer :: Config -> m Server
buildServer cfg = ...

Now every time I use those record fields I have to explicitly apply them to cfg to get what I want:

    let someFunction = doSomething (issuer cfg) (loadUser cfg) (authenticate cfg)

Previously I was just creating the functions in the same scope (without the configuration data type), so this was just:

    let someFunction = doSomething issuer loadUser authenticate

Is there some way I can say "when I refer to these record fields, they all apply to this instance" in a block of code, rather than having to repeat it every time? I remember coming across something like this in the past, but can't find it now, and I could be wrong.

2

2 Answers

12
votes

Yes, with the RecordWildCards extension:

buildServer (Config {..}) =
    let someFunction = doSomething issuer loadUser authenticate
    in undefined
7
votes

Without any syntax extensions, you can simply use the Applicative instance of the function arrow for a similar effect:

someFunction = doSomething <$> 
               issuer <*>
               loadUser <*>
               authenticate $ cfg

-- or

someFunction' = liftA3 doSomething issuer loadUser authenticate cfg

although that's of course not really a whole lot shorter.