question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Haskell-style Typeclasses

See original GitHub issue

When I first started rtype, I was tempted to just steal Haskell’s Hindley-Milner type annotations and just start using them, but I saw several problems with that:

  1. Haskell types are all curry all the time. I wanted to be able to express: add2(a: Number, b: Number) => Number.
  2. How do you deal with this?
  3. I wanted to be able to name parameters for clearer documentation. Haskell’s types are very expressive and clean-looking, but it’s sometimes hard to figure out what the type variables represent in real code.

So, we abandoned Hindley-Milner altogether, and forgot all about typeclasses. Ever since, we’ve been struggling with the question: How do we represent type polymorphism, and especially, higher order functions like map. Take Haskell’s Functor type:

fmap :: Functor f => (a -> b) -> f a -> f b

In this example, a and b are both type variables, and f a and f b mean “functor of a” and “functor of b”, respectively.

The Functor f => is called a type constraint. It basically says, “in this definition, f represents the Functor typeclass”. Like generic type constructors in other languages, a typeclass takes a type parameter, so f a represents a type that is a member of the Functor typeclass, and f b represents a possibly different type that also a member of the Functor typeclass.

We currently have no way to express this in rtype, and because I do a lot of functional programming, I have been falling back on Haskell’s Hindley-Milner types in a lot of my writing.

I’m frustrated with that because as I mentioned already, switching from rtype to Hindley-Milner or vice verse, we lose a lot of valuable information. Haskell’s Hindley-Milner notation doesn’t express enough about the names and purposes of variables, lacks …rest, etc…, and also doesn’t naturally allow for uncurried multi-arg functions.

If we try to express a lot of higher-order functions in rtype, it falls flat. To complicate matters, I’m building lots of types that implement a bunch of stuff with methods, meaning I need a way to say that map is a method on a Functor type, and takes this as an argument.

We need the best of both worlds.

Proposal

What if we could do this in rtype?

fmap = (a => b) => Functor(a) => Functor(b)

And for Mappables using this:

interface Mappable {
  map: Functor(a) ~> (a => b) => Functor(b)
}

Where Functor(a) is the type of this in the map method. The ~> for this syntax is lifted from the Fantasyland specification.

Instead of specifying a type constraint with a variable name, we’ll explicitly say Functor(a) or Functor(b) instead of f a or f b.

updateWhere = Predicate => (a => b) => Functor(a) => Functor(b)

updateWhere() is a curried function that takes a predicate, an updater function from a to b, (where a and b represent any type, and may refer to the same type), and a Functor of a, and returns a new Functor of b, with the matching elements replaced with updated versions.

Issue Analytics

  • State:open
  • Created 6 years ago
  • Comments:14 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
ericelliottcommented, Oct 9, 2018

Note to self: Update the syntax, clarify any lingering questions, create a PR.

I’m already using higher kinded types in lots of documentation.

0reactions
ericelliottcommented, Nov 22, 2018

Updated original proposal description. I’ve been using this syntax for quite a while now and testing it in mentorship sessions. Mentees seem to pick up what’s going on quickly, and people familiar with Haskell should be able to use what they know about Haskell to learn the ropes.

Read more comments on GitHub >

github_iconTop Results From Across the Web

A Gentle Introduction to Haskell: Classes
In Haskell, type classes provide a structured way to control ad hoc polymorphism, or overloading ... Type classes conveniently solve both of these...
Read more >
Haskell-style type classes with Isabelle/Isar - TUM
This tutorial demonstrates common elements of structured specifications and abstract reasoning with type classes by the algebraic hierarchy of ...
Read more >
Types and Typeclasses - Learn You a Haskell for Great Good!
Types and Typeclasses. Believe the type. moo. Previously we mentioned that Haskell has a static type system. The type of every expression is...
Read more >
Haskell/Classes and types - Wikibooks, open books for an ...
Broadly speaking, the point of type classes is to ensure that certain operations will be available for values of chosen types. For example,...
Read more >
Type Classes
Parametric polymorphism can be contrasted with overloading. In an influential his- torical paper, Christopher Strachey referred to Haskell-style polymorphism as ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found