Is there a Data.Binary instance for Data.Time.Calendar.Day? - haskell

Is there a Data.Binary instance for Data.Time.Calendar.Day?
More generally, what is one supposed to do if Data.Binary have not been provided for a particular datatype in a widely used library?

If you just create a Binary instance and place it in your module then you'll be creating an orphan instance which can cause a lot of confusion later when someone imports your module---it'll drag along that orphan instance and possibly conflict with their understanding of how dates should be made Binary.
If you have a very canonical instance, try pushing it to the library author. It's easy to add the instance if it's a good idea and it can benefit anyone who uses that library.
If that isn't an option (or if you have a non-canonical instance) then you probably want to create a newtype wrapper. They're "free" in that the compiler deletes them automatically, but they allow a type to take on an entirely new identity with new typeclass instances.
I've done this before to handle particular parses of, for instance, "dates in this format" compared to Date broadly.

Related

Haskell: Coherence rules wrt. external code

In Rust, I am not allowed (for good reasons) to for example implement libA::SomeTrait for libB::SomeType.
Are there similar rules enforced in Haskell, or does Haskell just sort of unify the whole program and make sure it's coherent as a whole?
Edit: To phrase the question more clearly in Haskell terms, can you have an orphan instance where the class and the type are defined in modules from external packages (say, from Hackage)?
It looks like you can have an orphan instance wrt. modules. Can the same be done wrt. packages?
Yes. In Haskell, the compiler doesn't really concern itself with packages at all, except for looking up which modules are available. (Basically, Cabal or Stack tells GHC which ones are available, and GHC just uses them.) And an available module in another package is treated exactly the same as a module in your own package.
Most often, this is not a problem – people are expected to be sensible regarding what instances they define. If they do define a bad instance, it only matters for people who use both libA and libB, and they should know.
If you do have a particular reason why you want to prevent somebody from instantiating a class, you should just not export it. (You can still export functions with that class in their constraint.)

`Show` instance for GHC core

I am trying to work with GHC core data types.
I am able to compile my Haskell source to core representation with type Bind CoreBndr.
As we know there is no default Show instance for this data type.
There is a way to pretty print this representation but it has way too much noise associated with it.
I want to treat GHC core as any other algebraic data type and write functions with it.
It would be much easier if we had a Show instance of GHC core.
Has anybody already written a show instance which I can reuse?
Aside, how does the community write and verify programs that deal with GHC core?
A naive implementation of Show in GHC is probably not what you want. The reason for this is because internally GHC has recursion among many of its data types. For instance, between TyCon, AlgTyConRhs, and DataCon we have:
TyCon has AlgTyCon, which contains AlgTyConRhs.
AlgTyConRhs contains data_cons :: [DataCon] as one of its record fields.
DataCon contains dcRepTyCon :: TyCon as one of its fields.
And thus we come full circle. Because of how Show works, recursion like this will create infinite output if you ever attempt to print it.
In order to get a "nice" custom representation with data constructors and everything showing, you would have to write it yourself. This is actually somewhat challenging, since you have to consider and debug cases of recursion like this that default pretty printers have solved.

Getting safety and extensibility

I have a library that includes a type data Zq q = Zq Int representing the integers mod q. For safety, I'd like to expose some operations on this type ((+), (*), etc), but not export the constructor to avoid people circumventing the safety gotten by declaring such a type in the first place.
However, users of the library may reasonably need to declare instances for this type that I as the library author can't predict. To name just a few possible instances: DeepSeq, Storable, Unbox, ...
The only way I know of that allows third parties to make such instances is to export the constructor. (Alternatively, I could define and export a smart constructor and destructor, but this seems to be no better than just exporting the data constructor.)
Is there a way to ensure safety while also allowing third parties to extend the type?
Most well-formed instances shouldn't require the unsafe raw constructors. Unbox etc. are a bit unusually low-level, but other instances should generally be definable in terms of much the same high-level API you'd also use for end applications.
So, I don't really see your concern of don't know instances ⇒ can't hide constructors. If you just define the critical close-to-the-metal instances yourself you should be fine.
That said, I often find it rather annoying if a library doesn't export the constructors at all. Even if every instance and everything else can be defined only using the high-level API, it can make sense to grant unsafe low-level access for a lot of reasons that can't really be forseen. Debugging, special optimisations, simply seeing what's going on...Hence, in a similar vein to Python's “we're all consenting adults here” philosophy, I'd support kosmikus' suggestion: export the constructors of all important types, but do it in a way that makes it clear that using these directly is unsafe. An extra Unsafe module is a good way to achieve this. Simply giving the constructor a technical-sounding name may also be sufficient. And of course document what precisely is unsafe about these exports.

`deriving (Data)` vs `deriving (Generic)`

What's the difference between these two in GHC. They seem similar in intended purpose but deriving (Data) has been around for a while yet deriving (Generic) has only been added to GHC recently.
Is deriving (Generic) basically an "upgrade" to deriving (Data) or do the two classes have different purposes?
I almost hesitate to answer this question, because I only marginally understand it myself, but I did spend a couple of days looking at this myself about a year ago, and this is my current understanding....
Both classes are used for introspection.... Using them, you can get access to the Haskell code parsetrees (of the Haskell program itself).
Philosophically, the way that they do this differs, however.
deriving (Data) creates data objects, which represent the parsed tree of objects that can be manipulated at runtime.
deriving (Generic) creates new Types corresponding to each parsetree, which often can be manipulated at compile time (leaving less work to be done at runtime).
From my limited usage, "deriving (Data)" was much more straightforward to use, but of course wasn't as sleek at runtime (....for me this was negligable).
Although "deriving (Generic)" was theoretically faster, it was trickier to program, and involved creating classes that could manipulate groups of Types (ie- related parsetrees). It also may push you into using cutting edge GHC extensions.
My opinion- "deriving (Generic)" is the "right" way to do things, but would take longer to master.
Template Haskell is another way to access Haskell parsetrees, although it works 100% at compiletime, and has tools to let you create and insert parse tree data into the code (ie- code that generates code, like a Lisp macro).
Again, let me stress that this is all based on a couple of days of research, so if I have mangled this too badly, someone let me know (I myself would like to firm up my understanding).

Should lens generation be treated like instances

I have a data type defined in another library. I would like to hook into that datatype with a lens generated by the Control.Lens library.
Do I need to newtype my type in my code or is it considered safe to lens an already defined data type?
You don't need a newtype. There are actually many packages on hackage that define lenses for already existing types (for example, xml-lens or even lens itself).
The problem with defining instances is that there is no way to hide them. If you define lenses, you can just hide them when importing, like any other function:
import Module.Lens hiding (someGeneratedLens, ...)
This is not possible with instances (See https://stackoverflow.com/a/8731340/2494803 for reasons). Lenses are also not required to be globally unique, unlike instances.

Resources