Reputation: 89053
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
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