Re: Functional design question
Akhra Gannon <[email protected]> Sun, 22 Mar 2026 17:07:50 -0700
| Newsgroups | gmane.comp.lang.haskell.cafe |
|---|---|
| Message-ID | <CAJoPsuDpXVaox+CRpv2EQjPs6Yka+GbDjweuWqBEf1JD026B-g@mail.gmail.com> |
--===============2482828950825417300==
Content-Type: multipart/alternative; boundary="000000000000da44ca064da5d37c"
--000000000000da44ca064da5d37c
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
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
=3D 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)
On Sun, Mar 22, 2026, 4:10=E2=80=AFPM Joachim Durchholz <joachim@durchholz.=
org>
wrote:
> 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 -- [email protected]
> To (un)subscribe, modify options or view archives go to:
> Only members subscribed via the mailman list are allowed to post.
>
--000000000000da44ca064da5d37c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto">honestly, the way you've laid it out looks perfectly =
reasonable to me! it generally follows the principle ot "parse, don=
9;t validate" laid out here:=C2=A0<a href=3D"https://lexi-lambda.githu=
b.io/blog/2019/11/05/parse-don-t-validate/">https://lexi-lambda.github.io/b=
log/2019/11/05/parse-don-t-validate/</a><div dir=3D"auto"><br></div>the onl=
y 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 exa=
mining the other. this lets you do all the source-related analysis with mon=
omorphic code; and in cases where the final payload type is unchanged, you =
can just discard the tuple wrapper to finalize.<div dir=3D"auto"><br></div>=
<div dir=3D"auto">at the top level, for each final-config item I'd imag=
ine the process would (in Haskell) look something like:</div><div dir=3D"au=
to"><br></div><div dir=3D"auto">finalizeConfigValue</div><div dir=3D"auto">=
=C2=A0 :: (a -> Maybe b)</div><div dir=3D"auto">=C2=A0 -> [(SourceInd=
ex, a)]</div><div dir=3D"auto">=C2=A0 -> Maybe b</div><div dir=3D"auto">=
finalizeConfigValue valueParser</div><div dir=3D"auto">=C2=A0 =3D listToMay=
be</div><div dir=3D"auto">=C2=A0 . mapMaybe (valueParser . snd)</div><div d=
ir=3D"auto">=C2=A0 . sortOn fst</div><div dir=3D"auto"><br></div><div dir=
=3D"auto">with an Ord instance on SourceIndex, and the Maybe output represe=
nting failure of all candidates to parse (you could also use defaulting and=
/or exceptions)<br><div dir=3D"auto"><br><div dir=3D"auto"><br></div><div d=
ir=3D"auto"><div dir=3D"auto"><div dir=3D"auto"><div dir=3D"auto"><div clas=
s=3D"gmail_quote gmail_quote_container" dir=3D"auto"><div dir=3D"ltr" class=
=3D"gmail_attr">On Sun, Mar 22, 2026, 4:10=E2=80=AFPM Joachim Durchholz <=
;<a href=3D"mailto:[email protected]">[email protected]</a>> wro=
te:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex">Hi all,<br>
<br>
I have some design questions - not for Haskell but for the Java+Vavr <br>
combo, but I am about to dip my toes into actual work in a functional <br>
manner, as far as that is possible, and I thought I might as well go for <b=
r>
the community that's best subscribed to a purely functional style.<br>
<br>
Bird's eye view:<br>
<br>
Java everybody knows (I don't like it either, no worries), Vavr is a - =
<br>
to my eyes - pretty nice functional library, <a href=3D"https://docs.vavr.i=
o/" rel=3D"noreferrer noreferrer" target=3D"_blank">https://docs.vavr.io/</=
a> for <br>
details if you're actually interested.<br>
I want to leverage Vavr to get a Java program to be as Haskell-ish as is <b=
r>
reasonable; that's not going to be much by a Haskeller's standards,=
<br>
but... baby steps.<br>
<br>
Application is a simple command-line thing: Read configuration from <br>
command line and configuration file, emit diagnostics about any errors <br>
in the config, then process.<br>
I want the configuration processing to be as functional as reasonable, <br>
given the constraints. However, I'm undecides about many things, no <br=
>
doubt because I simply don't know the best design patterns, and it'=
s <br>
frustrating to see multiple options and not knowing which ones will <br>
paint me into a corner and which ones will not.<br>
<br>
Things I'm undecided about:<br>
<br>
a) Data type variations<br>
During the configuration phase, I need to carry information about where <br=
>
some configuration item came from (its ("context", usually file, =
line <br>
number, column number).<br>
In the processing phase, configuration is considered final and <br>
error-free, so context is not needed (that's a done design decision).<b=
r>
I could carry context information into the processing phase, but it's <=
br>
going to be awkward: Say, we have the following types (forgive the most <br=
>
un-Haskellish pseudo syntax but I don't dare to use Haskell style <br>
because I'd almost certainly get that wrong and provoke misunderstandin=
gs)<br>
=C2=A0 =C2=A0DirectoryConfig {<br>
=C2=A0 =C2=A0 =C2=A0ConfigData<Path> path<br>
=C2=A0 =C2=A0 =C2=A0ConfigData<String> title<br>
=C2=A0 =C2=A0 =C2=A0...<br>
=C2=A0 =C2=A0}<br>
=C2=A0 =C2=A0data ConfigData<a> {<br>
=C2=A0 =C2=A0 =C2=A0String fileName<br>
=C2=A0 =C2=A0 =C2=A0int lineNumber<br>
=C2=A0 =C2=A0 =C2=A0int columnNumber<br>
=C2=A0 =C2=A0 =C2=A0a value<br>
=C2=A0 =C2=A0}<br>
but in the processing phase I don't want my config objects polluted wit=
h <br>
context, so I want<br>
=C2=A0 =C2=A0DirectoryConfig {<br>
=C2=A0 =C2=A0 =C2=A0Path path<br>
=C2=A0 =C2=A0 =C2=A0String title<br>
=C2=A0 =C2=A0 =C2=A0...<br>
=C2=A0 =C2=A0}<br>
No idea how to deal with that. I'd use code generation in Java I guess,=
<br>
but that's horribly inelegant and complicated to set up (no, I don'=
t <br>
particularly like Java, it's just what I'm currently using).<br>
So... how would one do such a thing in a functional language?<br>
Not necessarily Haskell, I guess some language extensions exist for that <b=
r>
kind of stuff, but I'm more-or-less tied to Java + functional libraries=
, <br>
so I'll have to stick with the more basic approaches most likely. <br>
Besides, even if I did Haskell, I'd want to avoid the advanced stuff <b=
r>
until I get confident in the basics.<br>
<br>
TL;DR: I have a deeply nested configuration data structure where each <br>
field has a "context", i.e. the place it came from; how to I make=
it so <br>
that the context is available during configuration evaluation but is <br>
unavailable in the later processing phase?<br>
<br>
I hope this is understandable; it's really hard to do that when you <br=
>
don't even know enough to ask the questions precisely enough.<br>
<br>
Regards,<br>
Jo<br>
_______________________________________________<br>
Haskell-Cafe mailing list -- <a href=3D"mailto:[email protected]" ta=
rget=3D"_blank" rel=3D"noreferrer">[email protected]</a><br>
To (un)subscribe, modify options or view archives go to:<br>
Only members subscribed via the mailman list are allowed to post.<br>
</blockquote></div></div></div></div></div></div></div></div>
--000000000000da44ca064da5d37c--
--===============2482828950825417300==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Haskell-Cafe mailing list -- [email protected]
To (un)subscribe, modify options or view archives go to:
Only members subscribed via the mailman list are allowed to post.
--===============2482828950825417300==--