简体   繁体   中英

haskell — can one access type variables from an instance function declaration?

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.

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

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!

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
{-# LANGUAGE ScopedTypeVariables #-}
class A a where foo :: a b
instance A C where
    foo :: forall b. C b
    foo = undefined :: C b

Read more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM