<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">
Just for the record, the question still remains, but as usual, after I sent the question I realized the general ballpark in which the answer may end up being.<br>
<br>
When doing:</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">
<span style="font-family: Calibri, Arial, Helvetica, sans-serif, serif, EmojiFont; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">instance (forall b. (Ord a, Ord b)) => Class1 a where</span><br>
<span style="font-family: Calibri, Arial, Helvetica, sans-serif, serif, EmojiFont; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);"> fun1 = (<)</span><br>
<br>
While in this case there are no functional dependencies, it is possible in principle that (Ord a, Ord b) produces a functional dependency between a and b, which would make the specific "a" a function of whatever "b" is, and since "b" is existentially quantified,
then "a" would also be dependent on the specific type it ended up being instantiated to. Is this what's going on? In order to do this, undecidable things like exploring all the possible combinations of functional dependencies would need to be explored by the
compiler?<br>
<br>
Even if this was exactly the problem, I would still be very happy to hear ideas on how to deal with this without having to manually write down all of the constraints that do not include a specific type variable.<br>
<br>
Thanks again.<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> CASANOVA Juan<br>
<b>Sent:</b> 02 April 2021 13:54<br>
<b>To:</b> YueCompl via Haskell-Cafe <haskell-cafe@haskell.org><br>
<b>Subject:</b> Existential type variables in constraints</font>
<div> </div>
</div>
<style type="text/css" style="display:none">
<!--
p
{margin-top:0;
margin-bottom:0}
-->
</style>
<div dir="ltr">
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">
Hello again,</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">
Here with more type class issues.<br>
<br>
As usual, assume all extensions required. But here I am going to be explicit, because UndecidableInstances is definitely required for this and I know it's a problematic one. These may be excessive, but with these extensions this should work:<br>
<br>
{-# LANGUAGE MultiParamTypeClasses #-}
<div>{-# LANGUAGE FunctionalDependencies #-}</div>
<div>{-# LANGUAGE FlexibleInstances #-}</div>
<div>{-# LANGUAGE UndecidableInstances #-}</div>
<div>{-# LANGUAGE TypeSynonymInstances #-}</div>
<div>{-# LANGUAGE RankNTypes #-}</div>
<div>{-# LANGUAGE KindSignatures #-}</div>
<div>{-# LANGUAGE ScopedTypeVariables #-}</div>
<div>{-# LANGUAGE QuantifiedConstraints #-}</div>
<div>{-# LANGUAGE FlexibleContexts #-}</div>
<div>{-# LANGUAGE LiberalTypeSynonyms #-}</div>
<div>{-# LANGUAGE ExistentialQuantification #-}</div>
{-# LANGUAGE ConstraintKinds #-}<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">
<br>
My "problem" is I want (almost need) existentially quantified types in constraints. The reason is that I have lots, lots and lots of constraints over up to 10 type variables (multi-parameter type classes in most cases, with complex functional dependencies),
which are trickled down over multiple layers of functions over multiple modules. So what I do is I define some global type synonyms that combine families of these constraints, usually the ones that are used in a specific module. Something like:<br>
<br>
type ModuleAConstraints a b c d = (Ord a, Ord b , Ord c, Class1 a b, Class2 a [c], Class3 [(c,a)] (a -> d [b]))<br>
<br>
(the specific constraints are made up, mine are much more and more complicated, but you get the idea of the liberality of the constraints)<br>
<br>
Now, what happens is that in one of the highest-level modules, some of the type variables begin to disappear because they are only used internally in the lower-level modules. The functional dependencies ensure that, once I instantiate the remaining type variables,
those type variables will have only one possible result, for which I will have an implemented instance.<br>
<br>
But my type synonyms include them, and I need them to use the lower-level functions.<br>
<br>
No problem, you can have existentially quantified variables in constraints. For example, this works:<br>
<br>
class Class1 a where
<div> fun1 :: a -> a -> Bool</div>
<div><br>
</div>
<div></div>
instance (Ord a, forall b. Ord b) => Class1 a where<br>
fun1 = (<)<br>
<br>
You can also do this with type synonyms and group constraints into pairs. For example, the two following equivalent alternatives work (same definition of Class1):<br>
<br>
1:<br>
instance (Ord a, forall b c. (Ord b, Ord c)) => Class1 a where</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">
fun1 = (<)<br>
<br>
2:<br>
type CType b c = (Ord b, Ord c)
<div>instance (Ord a, forall b c. CType b c) => Class1 a where</div>
fun1 = (<)<br>
<br>
But, it seems, any constraints under the existentially quantifier that only utilize non-quantified variables seems to be completely overlooked by the compiler. As such, the following two equivalent alternatives both fail to type check, telling me that it cannot
deduce (Ord a):<br>
<br>
3:<br>
instance (forall b. (Ord a, Ord b)) => Class1 a where</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">
fun1 = (<)<br>
<br>
4:<br>
type CType a b = (Ord a, Ord b)
<div>instance (forall b. CType a b) => Class1 a where</div>
fun1 = (<)<br>
<br>
<br>
<br>
Is there a good reason for this? It could be a good reason in the sense of: The deduction would be incorrect; or a good reason in the sense of: The compiler would need to do undecidable things to be able to deduce that in general. But right now I cannot see
a reason. I honestly cannot see how it could be hard for the compiler to realize that<br>
<br>
instance (Ord a, forall b. Ord b) => Class1 a where<br>
fun1 = (<)<br>
<br>
and<br>
<br>
<span style="font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)">instance (forall b. (Ord a, Ord b)) => Class1 a where</span><br>
<span style="font-size:12pt; color:rgb(0,0,0); background-color:rgb(255,255,255)"> fun1 = (<)</span><br>
<br>
are equivalent. But it doesn't.<br>
<br>
Also, is there any way I can make this work? Right now, the only option I can see is to manually re-enumerate all of the constraints that do not include the quantified variable and use that. I guess I can do that and it would only take around an hour... but
what a boring and tedious hour, and to be fair I was going to stop for today anyway so I thought I'd throw the question on Haskell Cafe. I hope that's okay
<span id="x_🙂">🙂</span>.<br>
<br>
Thanks in advance as usual.<br>
Juan Casanova.<br>
</div>
</div>
The University of Edinburgh is a charitable body, registered in Scotland, with registration number SC005336. Is e buidheann carthannais a th’ ann an Oilthigh Dhùn Èideann, clà raichte an Alba, à ireamh clà raidh SC005336.
</body>
</html>