简体   繁体   中英

Instances for nested, parameterized types

Given that I have the data types

data A a = A a
data B b = B b

and the type class

class C c where
    f :: c a -> a

Now the class C expects a type of kind * -> * , so I can do

instance C A where
    f (A a) = a

instance C B where
    f (B b) = b

Now given a function such as:

ab :: b -> A (B b)
ab = A . B

How would I declare an instance of C for the result type?

I first through I might be able to use a type synonym with TypeSynonymInstances , like this:

type AB b = A (B b)
class C AB where
    f (A (B b)) = b

Especially since ghci reports the correct kind:

*Main> :k AB
AB :: * -> *

However, you can't seem to use partially applied type synonyms in instance declarations (or anywhere, for that matter).

Is there some way I can compose the types A and B like I can compose the constructors, or some other syntax for declaring an instance for such a nested type?

The simplest is probably to define

newtype AB a = AB { unAB :: A (B a) }

GHC should be able to derive a C instance for this.

You could also use TypeCompose to accomplish this,

type AB = A :. B

instance C AB where
  f = f . f . unO

There is no way to declare such an instance. In fact, allowing arbitrary type functions such as AB in instance declarations makes instance resolution undecidable.

Usually, the solution is to declare a newtype. Of course, you will have to explicitly convert to and from the newtype when you want to use the class.

newtype AB a = AB (A (B a))
instance C AB where f (AB (A (B a)) = a

If your usage of the class is simple enough, you may want to just pass the overloaded method as a parameter of functions that use it.

You have to use a newtype . A type synonym must always be applied completely, as it is only a synonym, not a lambda. A newtype has no runtime penalty; it will be removed when compiling.

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