honestly, the way you've laid it out looks perfectly reasonable to me! it generally follows the principle ot "parse, don't validate" laid out here: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
the only core change I might make is to remove the payload from ConfigData and use a tuple of (SourceIndex, a) instead, so you can operate on one without examining the other. this lets you do all the source-related analysis with monomorphic code; and in cases where the final payload type is unchanged, you can just discard the tuple wrapper to finalize.
at the top level, for each final-config item I'd imagine the process would (in Haskell) look something like:
finalizeConfigValue
:: (a -> Maybe b)
-> [(SourceIndex, a)]
-> Maybe b
finalizeConfigValue valueParser
= listToMaybe
. mapMaybe (valueParser . snd)
. sortOn fst
with an Ord instance on SourceIndex, and the Maybe output representing failure of all candidates to parse (you could also use defaulting and/or exceptions)
Hi all,
I have some design questions - not for Haskell but for the Java+Vavr
combo, but I am about to dip my toes into actual work in a functional
manner, as far as that is possible, and I thought I might as well go for
the community that's best subscribed to a purely functional style.
Bird's eye view:
Java everybody knows (I don't like it either, no worries), Vavr is a -
to my eyes - pretty nice functional library, https://docs.vavr.io/ for
details if you're actually interested.
I want to leverage Vavr to get a Java program to be as Haskell-ish as is
reasonable; that's not going to be much by a Haskeller's standards,
but... baby steps.
Application is a simple command-line thing: Read configuration from
command line and configuration file, emit diagnostics about any errors
in the config, then process.
I want the configuration processing to be as functional as reasonable,
given the constraints. However, I'm undecides about many things, no
doubt because I simply don't know the best design patterns, and it's
frustrating to see multiple options and not knowing which ones will
paint me into a corner and which ones will not.
Things I'm undecided about:
a) Data type variations
During the configuration phase, I need to carry information about where
some configuration item came from (its ("context", usually file, line
number, column number).
In the processing phase, configuration is considered final and
error-free, so context is not needed (that's a done design decision).
I could carry context information into the processing phase, but it's
going to be awkward: Say, we have the following types (forgive the most
un-Haskellish pseudo syntax but I don't dare to use Haskell style
because I'd almost certainly get that wrong and provoke misunderstandings)
DirectoryConfig {
ConfigData<Path> path
ConfigData<String> title
...
}
data ConfigData<a> {
String fileName
int lineNumber
int columnNumber
a value
}
but in the processing phase I don't want my config objects polluted with
context, so I want
DirectoryConfig {
Path path
String title
...
}
No idea how to deal with that. I'd use code generation in Java I guess,
but that's horribly inelegant and complicated to set up (no, I don't
particularly like Java, it's just what I'm currently using).
So... how would one do such a thing in a functional language?
Not necessarily Haskell, I guess some language extensions exist for that
kind of stuff, but I'm more-or-less tied to Java + functional libraries,
so I'll have to stick with the more basic approaches most likely.
Besides, even if I did Haskell, I'd want to avoid the advanced stuff
until I get confident in the basics.
TL;DR: I have a deeply nested configuration data structure where each
field has a "context", i.e. the place it came from; how to I make it so
that the context is available during configuration evaluation but is
unavailable in the later processing phase?
I hope this is understandable; it's really hard to do that when you
don't even know enough to ask the questions precisely enough.
Regards,
Jo
_______________________________________________
Haskell-Cafe mailing list -- haskell-cafe@haskell.org
To (un)subscribe, modify options or view archives go to:
Only members subscribed via the mailman list are allowed to post.