[Haskell-cafe] Trouble splitting up source into multiple files, when using data abstraction.
Ivan Lazar Miljenovic
ivan.miljenovic at gmail.com
Mon Apr 14 00:25:51 UTC 2014
On 14 April 2014 10:22, David Thomas <davidleothomas at gmail.com> wrote:
> A concern, to be sure. On the flip side, it might be better to know what
> you are actually exposing (also meaning fewer things would constitute a
> breaking change).
There is the convention that "if it's in a .Internal module, then
you're on your own: this module doesn't contribute towards breaking
changes in the API".
> On Apr 13, 2014 5:00 PM, "John Lato" <jwlato at gmail.com> wrote:
>> It's possible to restrict LogTree.Internal to be visible only within the
>> package (see cabal's other-modules field), but please don't do so. You will
>> inevitably fail at providing every necessary function or accommodating all
>> reasonable uses of your library. Then some user will either write their
>> own, use something else or, if you're lucky, fork your library and send you
>> a merge request. It will happen (unless you have no other users).
>> As a recent example, I was using a library that had an internal data
>> structure, 'A' (completely unexposed) as part of an exposed data structure
>> 'B'. Both had 'deriving Generic' clauses. However, the Generic instance of
>> 'B' was mostly useless because if you wanted to use the Generic instance to
>> declare e.g. 'instance Binary B', it's also necessary to create a Binary
>> instance for 'A'. Which was impossible for users, because 'A' was
>> completely unexposed. When I pointed this out, the library's author
>> graciously accepted a patch to expose the type constructor 'A' (I'm not
>> entirely happy with this solution either, but for now we can't think of
>> anything better).
>> You could take this as an implementation flaw of Generic as it's currently
>> implemented (which it possibly is), however I would hope you also take it as
>> a demonstration of how data abstraction can interact with many different
>> language features in often-subtle ways. I think erring on the side of
>> allowing users maximum freedom is the best choice for now (preferably
>> stashed in modules/functions with names like 'internal' or 'unsafe').
>> On Sun, Apr 13, 2014 at 7:02 AM, Luke Clifton <ltclifton at gmail.com> wrote:
>>> Hi David,
>>> I think you can do something like providing a LogTree.Internal module
>>> which you use internally and which exports everything you need, and making
>>> your LogTree module which re-exports only the safe subset which "unknown"
>>> code would then import. I don't think there is a way of stopping anyone from
>>> importing your LogTree.Internal module though.
>>> On Sun, Apr 13, 2014 at 9:42 PM, David Banas <capn.freako at gmail.com>
>>>> Hi all,
>>>> I’ve defined a typeclass, LogTree, and would like to put each instance
>>>> definition in its own source file, in order that LogTree.hs not grow to a
>>>> ridiculous length.
>>>> I’m attempting to use data abstraction, in order to future-proof the
>>>> user interface to this class.
>>>> So, for instance, I don’t make all of the data constructors defined in
>>>> LogTree accessible, via the module export list, but rather force the user to
>>>> use certain “helper” functions, instead.
>>>> However, the individual instance definitions do need access to these
>>>> data constructors, but they’re in a different source file.
>>>> Is this possible? That is, is it possible to provide different export
>>>> lists to “friendly” vs. “unknown” client code?
>>>> Haskell-Cafe mailing list
>>>> Haskell-Cafe at haskell.org
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
Ivan Lazar Miljenovic
Ivan.Miljenovic at gmail.com
More information about the Haskell-Cafe