rampion
rampion

Reputation: 89053

Polykinded type composition

I've got a couple type aliases that all fit a similar pattern:

type Foo f = Bar (Qoox f)
type Faa f = Bar (Qaax f)
type Moo f = Fez (Rxoo f)
type Maa f = Fez (Rxaa f)
-- ...

I want to make the aliases point-free, so I can use them on their own. Rather than define newtypes, I thought it'd be neat if I could do type-level composition:

type Foo = Bar `Compose1` Qoox
type Faa = Bar `Compose1` Qaax
type Moo = Fez `Compose2` Rxoo
type Maa = Fez `Compose2` Rxaa
-- ...

But I keep having to define multiple Compose types because the base types are of different kinds.

What I'd like is a polykinded type-level function

type family (.) (m :: k1 -> k) (n :: k2 -> k1) :: k2 -> k where

So I could just do

type Foo = Bar . Qoox
type Faa = Bar . Qaax
type Moo = Fez . Rxoo
type Maa = Fez . Rxaa
-- ...

But I suspect that might be beyond Haskell's current capabilities, and I don't want to waste time trying to implement the impossible.

Can such composition be done in Haskell using the extensions available in GHC8?

Upvotes: 4

Views: 184

Answers (1)

chi
chi

Reputation: 116139

I think GHC is not currently able to make those point-free.

GHCi 8.0 seems to accept this.

> :set -XPolyKinds
> type C (m :: k1 -> k) (n :: k2 -> k1) (t :: k2) = m (n t)
> :i C
type C (m :: k1 -> k) (n :: k2 -> k1) (t :: k2) = m (n t) :: k

However, note that this can not be partially applied, in general, and will require you to eta-expand your definitions.

E.g. we can't use type T = C [] [] but we can use type T a = C [] [] a.

Without eta-expansion, I don't think we can return a type of kind k2 -> k unless that's a type constructor. We don't have type-level lambdas (or partial application).

Upvotes: 5

Related Questions