<div dir="auto">Haskell 98/2010 keeps a strict distinction between term-level syntax and tokens vs type-level.</div><div dir="auto"><br></div><div dir="auto">With ExplicitTypeApplications that's being eased: there's a lightweight way to sneak a type expression into a term. And ghc's internal term language 'core' has had explicit type applications for many years.</div><div dir="auto"><br></div><div dir="auto">Then consider a lightweight syntax using type applications in patterns to define typeclass instances by (pattern) 'matching' on types:</div><div dir="auto"><br></div><div dir="auto">> (==) @Int x y = primEqInt x y         -- or eta-reduced</div><div dir="auto">> (==) @Int     = primEqInt             -- shorthand for</div><div dir="auto">></div><div dir="auto">> instance Eq Int where</div><div dir="auto">>   (==) = primEqInt</div><div dir="auto"><br></div><div dir="auto">Given that many typeclasses have a single method (or one base method with others defined in terms of it) [Note **], having to invent a typeclass name is a bit of a pain. Here's a lighweight method decl:</div><div dir="auto"><br></div><div dir="auto">> meth :: @a @b. => a -> b -> Bool      -- typevar binding to left of => (there might also be superclass constraints)</div><div dir="auto">>                                       -- shorthand for</div><div dir="auto">></div><div dir="auto">> class Classfor_meth a b where         -- generated class name</div><div dir="auto">>   meth :: a -> b -> Bool</div><div dir="auto"><br></div><div dir="auto">Do we need class names at all? We could sneak term-level names into types. Just use the method name in constraints (with some handy syntactic marking -- what could be better than prefix @):</div><div dir="auto"><br></div><div dir="auto">> meth2 :: (@meth a b, @show b) => a -> b -> String</div><div dir="auto">> meth2 x y = if (meth x y) then show y else "blah"</div><div dir="auto"><br></div><div dir="auto">Of course we can infer the constraints on `meth2`, given its equation.</div><div dir="auto"><br></div><div dir="auto">Note **:  for some of the Prelude's classes with many methods, like Num, there's long-standing complaints that the methods are too much tangled up and should be refactored into a hierarchy with a single method in each class: Additive, Multiplicative, Divisive, etc.</div><div dir="auto"><br></div><div dir="auto">With type families we can tackle the classic collections class (with methods empty, insert) as a superclass constraint , er, supermethod method:</div><div dir="auto"><br></div><div dir="auto">> type family Elem c :: *</div><div dir="auto">> insert @c. => c -> Elem c -> c</div><div dir="auto">></div><div dir="auto">> empty :: @c. (@insert c) => c         -- entangle empty with insert</div><div dir="auto"><br></div><div dir="auto">Likewise for Monad:</div><div dir="auto"><br></div><div dir="auto">> (>>=) :: @m. => (m a) -> (a -> m b) -> (m b)</div><div dir="auto">></div><div dir="auto">> return :: @m. (@>>= m) => a -> m a</div><div dir="auto"><br></div><div dir="auto">The soon-to-arrive Quantified Constraints extension will provide further ways to entangle methods/constraints. That might be an alternative way to express collections:</div><div dir="auto"><br></div><div dir="auto">> insert @c @e. (e ~ Elem c) => c -> e -> c</div><div dir="auto">></div><div dir="auto">> empty @c. (forall e. @insert c e => @empty c) => c</div><div dir="auto"><br></div><div dir="auto">Of course all the above syntax is speculative/bikesheddable. The syntax needs to differentiate tyvars that are parameters/overloadable to the class/method vs parametric free tyvars. With explicit forall:</div><div dir="auto"><br></div><div dir="auto"><div dir="auto">> (>>=) :: forall m a b. @m. => (m a) -> (a -> m b) -> (m b)</div><div dir="auto">></div><div dir="auto">> return :: forall m a. @m. (@>>= m) => a -> m a</div><div dir="auto"><br></div><div dir="auto">Or perhaps method signatures should look more like methods-as-constraints -- at cost of a bit of repetition</div><div dir="auto"><br></div><div dir="auto">> (>>=) :: forall m a b. (@>>= m) => (m a) -> (a -> m b) -> (m b)</div><div dir="auto">></div><div dir="auto">> return :: forall m a. (@return m, @>>= m) => a -> m a</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">AntC</div></div>