4

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?

0

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

1 Comment

The ∀ a . is optional above -- a is in scope anyway according to GHC. Perhaps it's a good style to include it anyway, as we have to do elsewhere to bring a in scope. (To be honest, I never used that, and did not know that one can use forall in instances)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.