<div dir="ltr"><div class="gmail_quote"><div dir="ltr">Consider<div><br></div><div>><span style="font-family:Arial,Helvetica,sans-serif">    pattern PPoint :: Floating a => a -> a -> (a, a)   --  => ()</span></div>>    pattern PPoint x y = (x, y)<br>>    originP = PPoint 0 0<br>>    scaleP w (PPoint x y) = PPoint (w*x) (w*y)<br><div><br></div><div>Inferred `scaleP :: Floating a => a -> (a, a) -> (a, a)` -- so more restrictive than the `Num a` that would be inferred usually for `scaleP`'s `(*)` operator.</div><div><br></div><div>Ok what's the type-level analogue for `PPoint`, so that I can give signatures, instances, etc for methods using it? The type is not this:</div><div><br></div><div>>    type CPoint a = Floating a => (a, a)</div><div><br></div><div>(Needs `RankNTypes` to put a constraint in RHS of a type synonym.) This seems to get accepted:</div><div><br></div><div>> <span style="font-family:Arial,Helvetica,sans-serif">    scaleP :: a -> CPoint a -> CPoint a</span></div><div><br></div><div>Inferred `scaleP :: Floating a => a -> CPoint a -> (a, a)` -- that un-expanded `CPoint a` hints at a lurking danger. I couldn't for example write the equation for `scaleP` with a type annotation</div><div><br></div><div>>    scaleP w (PPoint x y) = PPoint (w*x) (w*y) :: CPoint a<br><div></div></div><div><br></div><div>Despite the annotation giving the result type exactly per the signature, this gives 'rigid type variable' rejections. This works (needs `ScopedTypeVariables`)</div><div><br></div><div>>    scaleP (w :: a) (PPoint x y) = PPoint (w*x) (w*y) :: CPoint a<br><div></div></div><div><br></div><div></div><div>What I especially want is instances and constraints:</div><div><br></div><div>><span style="font-family:Arial,Helvetica,sans-serif">    instance C1 (CPoint a)              --     * Illegal qualified type: Floating a => (a, a)</span></div>>                                            --     * In the expansion of type synonym `CPoint'<br>>    instance (C1 (CPoint a)) => C2 a  --    * Illegal qualified type: Floating a => (a, a)<br>>                                            --      GHC doesn't yet support impredicative polymorphism<br><div><br></div><div>(Needs `FlexibleInstances` to appear in the instance head, `FlexibleContexts` to appear in the constraint.) But I don't want to embed a qualified type in the instance head nor constraints, I want the expansion to be</div><div><br></div><div>>    instance (Floating a) => C1 (a, a)</div><div>>    instance (C1 (a, a), Floating a) => C2 a</div><div><br></div><div>It's kinda the constraint is 'outside' the constructed type; as if the synonym were given by</div><div><br></div><div>>    type (Floating a) => CPoint a = (a, a)</div><div><br></div><div>With the idea that when the compiler is expanding `CPoint a`, it floats the associated constraint out to the context the synonym call appears in. That is, I'm treating the expansion as very early in the compiler pipeline, just after syntax checking, before type inference/checking.</div><div><br></div><div>If that constraint-outside syntax in the type synonym decl seems familiar, you might have seen it discussed briefly in [Jones, Morris, Eisenberg 2020 Partial Type Constructors], Section 7 Related Work 'Datatype contexts in Haskell'. Let me emphasise I'm talking here about type synonyms _not_ Datatypes.</div><div><br></div><div>That constraint-outside syntax got rejected very early in the history of Haskell, apparently because nobody could give an adequate specification. Is my expand-it-as-syntax proposal not viable?</div><div><br></div><div>AntC</div></div>
</div></div>