I'm not familiar with GHC internals but I have a couple questions about ConstraintKinds.
It says from GHC.Exts that
data Constraint :: BOX
which is misleading because Constraint is a kind of sort BOX. This brings us to the first question: we can import and export kinds? How does that work?
Please correct me on this next part if I'm totally off. From trying out different imports and glancing around at the source on hackage, my guess is that GHC.Exts imports Constraint from GHC.Base, who in turn, imports it from GHC.Prim. But I do not see where it is defined in GHC.Prim?
To my knowledge, there is no definition of Constraint in any Haskell source file. It's a built-in, wired-in name that is defined to belong within GHC.Prim in the GHC sources itself. So in particular Constraint is not a promoted datatype, there's no corresponding datatype of kind * that is called Constraint.
There are other kinds in GHC that are treated similarly, such as AnyK, OpenKind or even BOX itself.
GHC doesn't really make a big difference internally between datatypes and kinds and anything above. That's why they e.g. all show up as being defined using data albeit with different target kinds.
Note that as far as GHC is concerned, we also have
data BOX :: BOX
It's impossible for a user to directly define new "kinds" of super-kind BOX, though.
As far as I know, importing / exporting also makes no difference between the type and kind namespaces. So e.g.
import GHC.Exts (OpenKind, BOX, Constraint)
is legal. In fact, if you then say
x :: Constraint
x = undefined
you don't get a scope error, but a kind error, saying that a type of kind * is expected, but a type/kind of kind BOX is provided.
I should perhaps also say that the whole story about kinds is somewhat in flux, and there are proposals being discussed that change this a bit: see e.g. https://ghc.haskell.org/trac/ghc/wiki/NoSubKinds for related discussion.
Related
When learning about Control.Arrow and Haskell's built-in proc notation, I had the idea that this language might prove very useful as an eDSL for general monoidal categories (using *** for tensor and >>> for composition), if only the Arrow typeclass were generalized to allow a general tens :: * -> * -> * operation rather than Arrow's (,) : * -> * -> *.
After doing some research, I found GArrows, which seem to fit my needs. However, the linked Garrow typeclass comes bundled with the so-called "HetMet" GHC extensions, and support for other features that (for the time being, anyway), I don't have much use for, such as "modal types".
Given that I would like to be able to use such a GArrow typeclass without having to install non-standard GHC extensions:
Is there an actual (somewhat standardized) library on Hackage that meets my needs for such a generalized arrow typeclass?
Given such a library, is there any way to use such a GArrow type class with a "generalized proc" notation without having to cook up my own GHC extension? (With RebindableSyntax perhaps?)
Note: Also, I'm fine with using quasiquotation for a generalized proc notation. So perhaps it wouldn't be too difficult to modify something like this to suit my needs.
I've wondered about that before, too. But – proc notation is so widely considered a silly oddball that there's probably not much interest in generalisation either (though I daresay this is what would make it actually useful!)
However, it's actually not necessary to have special syntax. The primary reference that must be named here is Conal Elliott's work on compiling lambda notation to bicartesian closed categories. Which I thought would have caught on in the Haskell community some time by now, but somehow hasn't. It is available as a GHC plugin, at any rate.
Even that isn't always needed. For some category combinators, you can just wrap a value that's universally quantified in the argument, and treat that as a pseudo-return-value. I call those Agent in constrained-categories; not sure if that's usable for your application, at any rate several things you'd do with arrow-like categories can be done. (In constrained-categories, the tensor product is fixed to (,), however, so probably not what you want. Although, could you explain what tensor product you need?)
My primary queston is: is there, within some Haskell AST, a way I can determine a list of the available declarations, and their types? I'm trying to build an editor that allows for the user to be shown all the appropriate edits available, such as inserting functions and/or other declared values that can be used or inserted at any point. It'll also disallows syntax errors as well as type-errors. (That is, it'll be a semantic structural editor, which I'll also use the typechecker to make sure the editing pieces make sense to in this case, Haskell).
The second part of my question is: once I have that list, given a particular expression or function or focussed-on piece of AST (using Lens), how could I filter the list based on what could possibly replace or fit that particular focussed-on AST piece (whether by providing arguments to a function, or if it's a value, just "as-is"). Perhaps I need to add some concrete example here... something like: "Haskell, which declarations could possibly be applied (for functions) and/or placed into the hole at yay x y z = (x + y - z) * _?" then if there was an expression number2 :: Num a => a ; number2 = 23 it would put this in the list, as well as the functions available in the context, as well as those from Num itself such as (+) :: Num a => a -> a -> a, (*) :: Num a => a -> a -> a, and any other declarations that resulted in a type that would match such as Num a => a etc. etc.
More details follow:
I’ve done a fair bit of research into this area over quite a long time: looked at and used hint, Language.Haskell.Exts and Control.Lens a fair bit. Also had a look into Dynamic. Control.Lens is relevant for the second half of my question. I've also looked at quite a few projects along the way including Conal Elliott's "Semantic Editing Combinators", Paul Chiusano's Unison system and quite a few things in Clojure and Lisp as well.
So, I know I can get a list of the exports of a module with hint as [String], and I could coerce that to [Dynamic], I think (possibly?), but I’m not sure how I’d get sub-function declarations and their types. (Maybe I could take the declarations within that scope with AST and put them in their own modules in a String and pull them in by getting the top level declarations with hint? that would work but feels hacky and cumbersome)
I can use (:~:) from Data.Typeable to do "propositional equality" (ie typechecking?) on two terms, but what I actually need to do is see if a term could be matched into a position in the source/AST (I'm using lenses and prisms to focus on those parts of the AST) given some number of arguments. Some kind of partial type-checking, or result type-checking? Because the thing I might be focussing on could very well be a function, and I might need to keep the same arity.
I feel like perhaps this is very similar to Idris' term-searching, though I haven't looked into the source for that and I'm not sure if that's something only possible in a dependently typed language.
Any help would be great.
Looks like I kind of answered my own questions, so I'm going to do so formally here.
The answer to the first part of my question can be found in the Reflection module of the hint library. I knew I could get a list a [String] of these modules, but there's a function in there that can be used which has type: getModuleExports :: MonadInterpreter m => ModuleName -> m [ModuleElem] and is most likely the sort of thing I'm after. This is because hint provides access to a large part of the GHC API. It also provides some lookup functions which I can then use to get the types of these top level terms.
https://github.com/mvdan/hint/blob/master/src/Hint/Reflection.hs#L30
Also, Template Haskell provides some of the functionality I'm interested in, and I'll probably end up using quite a bit of that to build my functions, or at least a set of lenses for whatever syntax is being used by the code (/text) under consideration.
In terms of the second part of the question, I still don't have a particularly good answer, so my first attempt will be to use some String munging on the output of the lookup functions and see what I can do.
I've been playing with Haskell's -XDataKinds feature quite a lot recently, and have found myself wanting to create a kind.
I'm not sure if my wishes can come true, but from Edward Kmett's constraints package, there seems to be a declared kind Constraint (with sort BOX), which says to be defined in GHC.Prim, but I couldn't find it.
Is there any way to declare a kind in Haskell or GHC, manually? This would probably need manual assertion that data types declared with data would be of the proper kind. My idea is something like the following:
data Foo :: BOX
data Bar a :: Foo where
Bar :: a -> Bar a
In current GHC (7.8 at time of writing), one cannot separate the declaration of a fresh kind from the declaration of its type-level inhabitants.
Suppose I have the following class:
class P a where
nameOf :: a -> String
I would like to declare that all instances of this class are automatically instances of Show. My first attempt would be the following:
instance P a => Show a where
show = nameOf
My first attempt to go this way yesterday resulted in a rabbit warren of language extensions: I was first told to switch on flexible instances, then undecidable instances, then overlapping instances, and finally getting an error about overlapping instance declarations. I gave up and returned to repeating the code. However, this fundamentally seems like a very simple demand, and one that should be easily satisfied.
So, two questions:
Is there a trivially easy way to do this that I've just missed?
Why do I get an overlapping instances problem? I can see why I might need UndecidableInstances, since I seem to be violating the Paterson condition, but there are no overlapping instances around here: there are no instances of P, even. Why does the typechecker believe there are multiple instances for Show Double (as seems to be the case in this toy example)?
You get the overlapping instances error because some of your instances of P may have other instances of Show and then the compiler won't be able to decide which ones to use. If you have an instance of P for Double, then there you go, you get two instances of Show for Double: yours general one and the one already declared in Haskell's base library. How this error is triggered is correctly stated by #augustss in the comments to your question. For more info see the specs.
As you already know, there is no way to achieve what you're trying without the UndecidableInstances. When you enable that flag you must understand that you're taking over the compiler's responsibility to ensure that there won't arise any conflicting instances. This means that, of course, there mustn't be any other instances of Show produced in your library. This also means that your library won't export the P class, which will erase the possibility of users of the library declaring the conflicting instances.
If your case somehow conflicts with the said above, it's a reliable sign of that there must be something wrong with it. And in fact there is...
What you're trying to achieve is incorrect above all. You are missing several important points about the Show typeclass, distinguishing it from constructs like a toString method of popular OO languages:
From Show's haddock:
The result of show is a syntactically correct Haskell expression containing only constants, given the fixity declarations in force at the point where the type is declared. It contains only the constructor names defined in the data type, parentheses, and spaces. When labelled constructor fields are used, braces, commas, field names, and equal signs are also used.
In other words, declaring an instance of Show, which does not produce a valid Haskell expression, is incorrect per se.
Given the above it just doesn't make sense to declare a custom instance of Show when the type allows to simply derive it.
When a type does not allow to derive it (e.g., GADT), generally you'll still have to stick to type-specific instances to produce correct results.
So, if you need a custom representation function, you shouldn't use Show for that. Just declare a custom class, e.g.:
class Repr a where
repr :: a -> String
and approach the instances declaration responsibly.
Apparently it's a bad idea to put a typeclass constraint on a data declaration [src], [src].
I haven't personally come across a desire to constrain the types within data types I've created, but it's not obvious to me why the language designers "decided it was a bad idea to allow". Why is that?
I haven't personally come across a desire to constrain the types within data types I've created, but it's not obvious to me why the language designers "decided it was a bad idea to allow". Why is that?
Because it was misleading and worked completely backwards from what would actually be useful.
In particular, it didn't actually constrain the types within the data type in the way you're probably expecting. What it did do was put a class constraint on the data constructor itself, which meant that you needed to satisfy the instance when constructing a value... but that was all.
So, for instance, you couldn't simply define a binary search tree with an Ord constraint and then know that any tree has sortable elements; the lookup and insert functions would still need an Ord constraint themselves. All you'd prevent would be constructing an empty tree that "contains" values of some non-ordered type. As far as pattern matching was concerned, there was no constraint on the contained type at all.
On the other hand, the people working on Haskell didn't think that the sensible version (that people tended to assume data type contexts provided) was a bad idea at all! In fact, class constraints on a data type declared with GADT syntax (generalized algebraic data types, enabled in GHC with the GADTs language pragma) do work in the obvious way--you need a constraint to construct the value, and the instance in question also gets stored in the GADT, so that you don't need a constraint to work with values, and pattern matching on the GADT constructor lets you use the instance it captured.
It's not actually a bad idea to add a typeclass constraint on a
data type - it can be very useful, and doesn't break your other code.
The badness is all about the fact that often people expect that they can then
use the data type to excuse them from putting a constraint on functions
that use the data type, but that's not the case.
(You could argue that an implicit constraint can cause problems.)
Putting a constraint on a datatype actually puts it on the all the constructors
that mention the constrained type.
Just as with an ordinary function with a constraint, if you use the constructor,
you must add the constraint. I think that's healthy and above board.
It does ensure you can't put data in your data type unless you can do
certain things with it. Its useful. You won't be creating a programming
faux pas by using one, and it's not bad practice, it's just not as lovely as
they wanted.
The "bad idea to allow" is probably because GADTs is really what they would like.
If GADTs had been around first, they wouldn't have done this.
I don't think it's such a bad thing to have both. If you want a state
manipulating function, you can use a permanently explicit parameter you pass around,
or you can use a monad and make it implicit. If you want a constraint on
data you can use a permanently explicit one on a data declaration or an implicit one
with a GADT. GADTs and monads are more sophisticated, but it doesn't make
explicit parameters or data type constraints wrong.