Re: Soundness of forall mixed with Coercible

Tom Ellis <[email protected]> Fri, 12 Dec 2025 23:46:53 +0000
Newsgroups gmane.comp.lang.haskell.cafe
Message-ID <aTypbVSiVcOnLItE@cloudinit-builder>
Well, the newtype Forall is about as useful as the forall quantifier.
For example, `forall a. a -> a -> a` is isomorphic to `Forall T`,
where `newtype T a = MkT (a -> a -> a)`.  So why have `Forall` if we
have `forall`?  Well, I can't abstract over the body of `forall`, so
the best I can do is use a one-parameter type variable (say `f`)
and use `Forall f` instead.

Here's an example of where `Forall f` is very different from `Void`.
`Forall L` is the type of lists of elements that can be Ordered and
Shown, where `newtype L a where MkL :: (Show a, Ord a) => [a] -> L a`.

But the actual use case I have is in my effect system Bluefin, where I
want to provide combinators that can be used to build new effects with
zero additional overhead (which is why I need the Coercible instance I
was asking about):

https://github.com/tomjaguarpaw/bluefin/commit/87ab865f1a7c246374df2d381d26ada96308ba0e#diff-a6f1b01c2f813ba98bbdbb57516f3268c0b122aa0548c4a4536ee40b8e2ef487R818-R834

Tom



On Fri, Dec 12, 2025 at 04:50:41PM +0200, Georgi Lyubenov wrote:
> In that case the `a` is still not really "present", i.e. the only
> inhabitants of `Forall Predicate` would be `MkForall (Predicate \_ -> True)`
> and `MkForall (Predicate \_ -> False)`, unless, again, I'm totally missing
> something here.
> It's true that here if you instead have Predicate Void you gain an
> additional value `Predicate \case`, but it still stands that you can't
> actually "use anything about the a", so I'm still curious regarding what the
> use case here is.
> 
> On 12/12/25 16:38, Zemyla wrote:
> > Wait, no, I forgot about values that aren't covariant. Forall $
> > Predicate $ const True is a valid value.
> > 
> > On Fri, Dec 12, 2025, 08:34 Georgi Lyubenov <[email protected]>
> > wrote:
> > 
> >     Yeah, I think this is my intuition which I was trying to get at
> >     with my "isn't this Void" comment - it seems to me that in all
> >     cases where you have a `forall a. f a` that would be the same
> >     thing as having an `f Void`, i.e. the `a` is never relevant or
> >     alternatively the f a inside a Forall will never actually contain
> >     an a.
> > 
> >     Is there still something else that I'm missing?
> > 
> >     What's the concrete use case for Forall?
> > 
> >     On 12/12/25 16:03, Zemyla wrote:
> > >     Wouldn't the only inhabited value of Forall [] be []?
> > > 
> > >     On Fri, Dec 12, 2025, 02:18 Adam Gundry <[email protected]> wrote:
> > > 
> > >         Hi Tom,
> > > 
> > >         You may be interested in a ticket where a similar issue was
> > >         discussed
> > >         before: https://gitlab.haskell.org/ghc/ghc/-/issues/20048
> > > 
> > >         Given `forall a . Coercible (f a) (g a)` it seems intuitively
> > >         obvious
> > >         that it should be sound to derive `Coercible f g`, but Core's
> > >         typing
> > >         rules don't currently allow it. Since Core is proof
> > >         irrelevant it is
> > >         probably safe just to add it, but actually proving soundness
> > >         would take
> > >         a bit of work.
> > > 
> > >         That said, you are asking about the subtly different
> > > 
> > >              Coercible (forall a . f a) (forall a . g a)
> > > 
> > >         which is derivable from `Coercible f g`, but in fact I think
> > >         is also
> > >         derivable from `forall a. Coercible (f a) (g a)` in today's
> > >         Core type
> > >         system. The difficulty seems to be that GHC's constraint
> > >         solver for
> > >         equality/Coercible constraints is incomplete in the presence of
> > >         quantified constraints. So unsafeCoerce seems defensible in
> > >         this case.
> > > 
> > >         Cheers,
> > > 
> > >         Adam
> > > 
> > > 
> > >         On 11/12/2025 17:58, Tom Ellis wrote:
> > >         > Oh, I forgot to give the definition of Forall, so I may as
> > >         well define
> > >         > it in its full glory, imports, extensions and all:
> > >         >
> > >         > {-# LANGUAGE QuantifiedConstraints #-}
> > >         >
> > >         > import Data.Coerce (Coercible)
> > >         > import Data.Type.Coercion (Coercion (Coercion))
> > >         > import GHC.Exts (Any)
> > >         > import Unsafe.Coerce (unsafeCoerce)
> > >         >
> > >         > newtype Forall f = MkForall (forall a. f a)
> > >         >
> > >         > forallCoercible ::
> > >         >    forall f g.
> > >         >    (forall a. Coercible (f a) (g a)) =>
> > >         >    Coercion (Forall f) (Forall g)
> > >         > forallCoercible =
> > >         >    unsafeCoerce (Coercion @(f Any) @(g Any))
> > >         >
> > >         > On Thu, Dec 11, 2025 at 05:47:25PM +0000, Tom Ellis wrote:
> > >         >>      forallCoercible ::
> > >         >>        forall f g.
> > >         >>        (forall a. Coercible (f a) (g a)) =>
> > >         >>        Coercion (Forall f) (Forall g)
> > >         >>      forallCoercible =
> > >         >>        unsafeCoerce (Coercion @(f Any) @(g Any))
_______________________________________________
Haskell-Cafe mailing list -- [email protected]
To (un)subscribe, modify options or view archives go to:
Only members subscribed via the mailman list are allowed to post.