[ghc-steering-committee] Discussion on proposal #99: forall {k}
Iavor Diatchki
iavor.diatchki at gmail.com
Tue May 1 16:56:20 UTC 2018
Hello,
I just re-read the proposal and I am a bit unclear: are we proposing that
we make this change only in type signatures or in all places where we bind
type variables? At first I thought we are talking only about type
signatures, but I noticed that the proposal seems to mention type classes,
but not `data` declarations or type families. I find the "implicit" hidden
parameters in those to be one of the most confusing features of GHC, so
having a way to write those would certainly be useful. I do have some
clarifying questions illustrated by the examples below (assuming that this
extension should work on `data`):
-- 1) The "normal" case. I've written the types of the introduces names
underneath, are they correct?
data T1 {k} (a :: k) = C1
-- T1 :: forall {k::Type}. k -> Type
-- C1 :: forall {k::Type} (a :: k). T1 {k} a
-- Am I correct in assuming that while GHC could print the types like that,
but users are not allowed to actually write those types (i.e., `T1 {k}
(a::k)` is not a valid type).
-- 2) Can GHC add extra inferred parameters? (This examples assumes
`PolyKinds`)
data T2 {k} a = C2
-- C2 :: forall {k1::Type} {k::Type} (a :: k1). T2 {k1} {k} a (ambiguous?)
-- 3) Can we infer non-kind types?
data T3 {a} = C3 a
-- C3 :: forall {a::Type}. a -> T3 {a}
-- 4) If `T3` is OK, how does "inferring" work in signatures? To make
things concrete, would the following be accepted?
f :: T3
f = C3 True
-- A): not, because the signature is really: `forall {a}. T3 {a}`.
-- B): yes, because we are going to infer that the missing type is `Bool`,
so the signature becomes `T3 {Bool}`.
-- 5) The proposal has a class, something like this:
class C a {b} where
meth1 :: a -> b
-- How do I write an instance for this class?
-- A)
instance C Int where
meth1 x = x
-- B)
instance C Int {Int} where
meth1 x = x
I imagine the answer is A) is I see nothing about writing types like
`{Int}`. If so, here are a couple of follow up questions about instances:
-- Valid?
instance C Int where
meth1 x = []
-- instance is really `forall {a::Type}. C Int {[a]}` ?
instance C Int where
meth1 x = return x
--- error, instance is `C Int {m Int}`, but no `Monad` constraint.
-- There doesn't seem to be a way to write the instance with the constraint?
Sorry for the long e-mail, but I hope that these examples might bring some
clarity to users of the proposed feature.
-Iavor
On Tue, May 1, 2018 at 3:55 AM Simon Peyton Jones <simonpj at microsoft.com>
wrote:
> [Redirecting to the steering committee]
>
>
>
> I argue for acceptance.
>
>
>
> - For me a compelling motivation is this: at the moment *we can infer
> types and kinds that we cannot write down with an explicitly-quantified
> type signature*. That seems all wrong to me: we should be able to
> write down any type you can infer.
> - The proposal adds *notation*. It does *not* add semantics. We
> already have the distinction between “inferred” and “specified” type
> variables. You might not like it, but it’s there in GHC.
> - If it wasn’t there already, I’d be happy to debate not adding
> it.
> - If you want to argue for removing the distinction, that would
> certainly render the current proposal moot. But that would take a GHC
> proposal – and there are good reasons for the status quo!
> - What is bad is to maintain the semantic distinction, but be
> unable to express it. That’s what we have right now, and it’s a bad thing.
>
>
>
> What is the distinction between “specified” and “inferred”?
>
> - *Specified. f :: forall a. blah, or f :: a -> a.*
>
> You may give a visible type argument at a call of f, but you do not have
> to. Thus (f x) or (f @type x).
>
>
>
> - *Inferred*. *f :: t a -> t a.* The type of f is really
>
> g :: forall {k} (t :: k -> *) (a :: k). t a -> t a
>
> Note that k does not appear at all in the signature; that’s why it is
> “inferred”. In GHC today you cannot supply an explicit kind argument for
> g, but you can supply explicit argument for t and a.
>
>
>
> So by all means make the case for abolishing the distinction, to render
> the present proposal moot. But I think it’s unreasonably simply to reject
> on the grounds of “please think of something better”.
>
>
>
> Simon
>
>
>
> *From:* ghc-devs <ghc-devs-bounces at haskell.org> *On Behalf Of *Iavor
> Diatchki
> *Sent:* 30 April 2018 17:12
> *To:* ghc-devs at haskell.org
> *Subject:* Discussion on proposal #99: forall {k}
>
>
>
> Hello,
>
>
>
> As a shepherd for proposal #99, I'd like to kick off the discussion. The
> full proposal is available here:
> https://github.com/goldfirere/ghc-proposals/blob/explicit-specificity/proposals/0000-explicit-specificity.rst
>
>
>
> Summary: allows programmers to write `forall {x}` instead of `forall x` in
> type signatures. The meaning of the braces is that this parameter cannot
> be instantiated with an explicit type application and will always be
> inferred. The motivation is to shorten explicit type applications by
> skipping parameters that are known to be inferable, the common example
> being omitting the kinds in signatures with poly kinds.
>
>
>
> As I understand it, the main motivation for this proposals is to give
> programmers more flexibility when instantiating type variables, with a less
> noisy syntax. While the proposed solution might work in some situations,
> I am unconvinced that it is the best way to address the issue in general,
> for the following reasons:
>
>
>
> 1. It requires that programmers commit at declaration time about which
> arguments will be inferred, and which may be inferred or specified. While
> in some cases this may be an easy decision to make, in many cases this
> really is a decision which should be made at the use site of a function
> (e.g., I'd like to provide argument X, but would like GHC to infer argument
> Y).
>
>
>
> 2. It still requires that programmers instantiate arguments in a fixed
> order, which is sometimes dictated by the structure of the type itslef.
> Here is, for example, what the proposal suggests to do if you want to
> provide type before a kind:
>
>
>
> typeRep4 :: forall {k} (a :: k) k'. (k ~ k', Typeable a) => TypeRep a
>
>
>
> While technically this is not wrong, it is not exactly elegant.
>
>
>
> I think that we should reject this proposal, and try to come up with a
> more comprehensive solution to the problem.
>
>
>
> One alternative design is to allow programmers to instantiate type
> variables by name. This is much more flexible as it allows programmers to
> instantiate whichever variables they want, and in whatever order. We've
> been doing this in Cryptol for a long time, and it seems to work really
> well.
>
>
>
> -Iavor
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-steering-committee/attachments/20180501/d9a2be6f/attachment.html>
More information about the ghc-steering-committee
mailing list