Why can I not use type variables in this instance declaration?

Viewed 293

I'm trying to use TypeApplications to disambiguate between which instance of a type class I am calling. Unfortunately, it seems that an instance declaration's type parameters cannot be used in the instance body. Specifically, in this toy example:

{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE TypeApplications     #-}
{-# LANGUAGE UndecidableInstances #-}

class Foo a where
    foo :: String

instance Foo () where
    foo = "()"

instance Foo Int where
    foo = "Int"

class Bar b where
    bar :: String

instance Foo a => Bar a where
    bar = foo @a

will error with Not in scope: type variable 'a' at the last line. If I remove the type application, instead the error Could not deduce (Foo a0) from the context Foo a is given, which is reasonable, ass foo by itself is ambiguous.

Is there some way for me to access the type parameter, or otherwise coerce the compiler into recognising this?

1 Answers

A type variable can be used in an instance declaration, but only if it's scoped:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE TypeApplications, AllowAmbiguousTypes   #-}
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax      #-}

class Foo a where foo :: String

class Bar b where bar :: String

instance āˆ€ a . Foo a => Bar a where
  bar = foo @a

As always, āˆ€ can also be written forall if you prefer ASCII.

Related