{instance (Default α) ⇒ DefConfig α} breaks things
akhra opened this issue · comments
• Overlapping instances for DefConfig SystemEnv
arising from a use of ‘gFromEnvCustom’
Matching instances:
instance data-default-class-0.1.2.0:Data.Default.Class.Default α =>
DefConfig α
-- Defined in ‘Magicbane’
instance DefConfig {redacted}
-- Defined at {redacted}
• In the expression:
gFromEnvCustom Option {dropPrefixCount = 1, customPrefix = ""}
In an equation for ‘fromEnv’:
fromEnv
= gFromEnvCustom Option {dropPrefixCount = 1, customPrefix = ""}
In the instance declaration for ‘FromEnv {redacted}’
This happens if Magicbane
is imported anywhere in the module's upstream dependency tree, even hiding everything; hooray for global instances. It's particularly disturbing that I have no idea where a Default
instance could have possibly come from for the type I'm trying to parse into.
In this case I'm able to work around it by only importing Magicbane.App
and Magicbane.HTTPClient
upstream. However, Default
is a widely-reviled antipattern and by preference I'd have it gone even if it didn't make things explode. On the other hand, killing it could cause significant downstream breakage.
Magicbane is imported anywhere in the module's upstream dependency tree
Wow, you're always doing some interesting stuff :) Magicbane was not intended to be used in libraries, only in applications.
Default
is a widely-reviled antipattern
Huh? Haven't heard about that. I like Default
.
I meant module dependencies, not package -- e.g. A
imports B
, B
imports Magicbane
, A
has this breakage.
I did also pull some code out into a library for sharing between different microservices. But shh. ;)
As for Default
: the simplest answer is that it is a class which effectively does nothing other than remove type safety. For any instance Default Foo
you could instead provide a unique defaultFoo
with the same amount of effort, and consumers of that value don't have to worry that they accidentally gave it the wrong type but one that still typechecks -- and this might seem like it should be a corner-case, but Data.Default
provides a pile of instances for things like Maybe a
and even (r -> a)
, and it doesn't take much searching to find horror stories about debugging the results.
For more nuanced commentary (and a few counterarguments), wander through the comments here. Several good blog links, threads by Tekmo and others.
hm, yeah, I guess, we don't really need that Default
. I like being able to just type def
instead of looking up defaultWhatExactly
, but it's not really that important.
Also I guess I'll make Magicbane
a reexport+orphan only module…