1

I want to access type variables in an instance, that don't show up in the instance's parameters. For example,

class A a where foo :: a b
data C a
instance A C where
    foo :: forall b. C b
    foo = undefined :: C b

Of course, the above will resolve without the scoped type expression, but I have a non-toy example where I actually want it.

edit

please try your code before pasting it as an answer! The above (Daniel's answer) results in

Test.hs:51:5: Misplaced type signature: foo :: forall b. C b
Failed, modules loaded: none.
gatoatigrado
  • 16,580
  • 18
  • 81
  • 143

4 Answers4

3

I think to overcome the problem with Daniel's solution that you are not allowed to provide a signature for a type class function you can simply define a top-level function and "rename" it in the instance of the type class. In your simple example the following should work.

{-# LANGUAGE ScopedTypeVariables #-}

class A a where 
    foo :: a b

instance A C where
    foo = foo'

foo' :: C b
foo' = undefined :: C b
Jan Christiansen
  • 3,153
  • 1
  • 19
  • 16
2

While a real solution would be preferable, one can work around the problem using asTypeOf, and adding dummy parameters. Here's an example,

class A a where foo2 :: b -> a b -- added parameter b
data C a
instance A C where
    foo2 x = undefined `asTypeOf` (wrapA x)

wrapA :: A C => a -> C a
wrapA = undefined

foo :: A a => a b
foo = foo2 undefined

That happened to work for my real-world example. cheers!

gatoatigrado
  • 16,580
  • 18
  • 81
  • 143
  • I think I finally understand what you are after -- it doesn't have anything to do with typeclasses per se, only that you can't use a scoped type variable if you can't bind the type variable in the first place! Very interesting (and I still don't know a better solution). – Owen Sep 12 '11 at 01:10
1

I think in the class declaration

class A a where
    foo :: a b

the type of foo is really

forall b. a b

ie foo should be sort of independent of the type b. Or, b is not actually part of the class A. So... I don't think you should need to be able to refer to it? Though I might not be understanding... maybe you could post an example where it is necessary?

If you need to keep the same type across more than one method you could use a multi-parameter type class:

class A a b where
    foo :: a b
    bar :: a b
Owen
  • 38,836
  • 14
  • 95
  • 125
  • That's my understanding of `foo`'s type too. But I want to access the `b` variable. See http://stackoverflow.com/questions/7382171/haskell-not-understanding-why-this-associated-type-example-needs-more-inferenc for a more complicated example of why one would like this. – gatoatigrado Sep 12 '11 at 00:10
  • @gatoatigrado I'm afraid your more complicated example is over my head. Still, I don't think it's possible to refer to `b` from within the instance -- `b` doesn't exist as part of the class or the instance. – Owen Sep 12 '11 at 00:17
0
{-# LANGUAGE ScopedTypeVariables #-}
class A a where foo :: a b
instance A C where
    foo :: forall b. C b
    foo = undefined :: C b

Read more.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380