On 2018-05-16 04:09, Anthony Clayden wrote:
Haskell 98/2010 keeps a strict distinction between term-level syntax and tokens vs type-level.

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.

Then consider a lightweight syntax using type applications in patterns to define typeclass instances by (pattern) 'matching' on types:

> (==) @Int x y = primEqInt x y         -- or eta-reduced
> (==) @Int     = primEqInt             -- shorthand for
>
> instance Eq Int where
>   (==) = primEqInt

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:

> meth :: @a @b. => a -> b -> Bool      -- typevar binding to left of => (there might also be superclass constraints)
>                                       -- shorthand for
>
> class Classfor_meth a b where         -- generated class name
>   meth :: a -> b -> Bool

As Oleg Kiselyov pointed out over a decade ago, all typeclasses can be reduced to just one, namely [1]

	class C l t | l -> t where ac :: l -> t

Which in turn is basically an untagged version of the HasField typeclass that's being used to create overloaded records. [2]

	class HasField (x :: k) r a | x r -> a where getField :: r -> a

(Not very surprising, because classes are basically compile-time records)

In other words

  1. You only have one class to replace (left as an exercise to the reader)
  2. I don't think you need any fancy new tricks or syntax for multi-function classes
  3. You might be able to also implement records with just type application and type families

Cheers,
MarLinn

[1] http://okmij.org/ftp/Haskell/Haskell1/Haskell1.txt
[2] https://github.com/adamgundry/ghc-proposals/blob/overloaded-record-fields/proposals/0000-overloaded-record-fields.rst#hasfield-class