Hi Alexis,
The following works and will have inferred type `Int`:
>
bar = foo (\(HNil :: HList '[]) -> 42)
I'd really like it if we could write
>
bar2 = foo (\(HNil @'[]) -> 42)
though, even if you write out the constructor type with explicit constraints and forall's.
E.g. by using a -XTypeApplications here, I specify the universal type var of the type constructor `HList`. I think that is a semantics that is in line with
Type Variables in Patterns, Section 4: The only way to satisfy the `as ~ '[]` constraint in the HNil pattern is to refine the type of the pattern match to `HList '[]`. Consequently, the local `Blah '[]` can be discharged and bar2 will have inferred `Int`.
If `'[]` is never mentioned anywhere in the pattern like in the original example, I wouldn't expect it to type-check (or at least emit a pattern-match warning): First off, the type is ambiguous. It's a similar situation as in
https://stackoverflow.com/questions/50159349/type-abstraction-in-ghc-haskell. If it was accepted and got type `Blah as => Int`, then you'd get a pattern-match warning, because depending on how `as` is instantiated, your pattern-match is incomplete. E.g., `bar3 @[Int]` would crash.
Complete example code:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
module Lib where
data HList as where
HNil :: forall as. (as ~ '[]) => HList as
HCons :: forall as a as'. (as ~ (a ': as')) => a -> HList as' -> HList as
class Blah as where
blah :: HList as
instance Blah '[] where
blah = HNil
foo :: Blah as => (HList as -> Int) -> Int
foo f = f blah
bar = foo (\(HNil :: HList '[]) -> 42) -- compiles
bar2 = foo (\(HNil @'[]) -> 42) -- errors
Cheers,
Sebastian