4
votes

I want to define a Functor instances for the following classes:

class RequiresManifest[A: Manifest] {
  def value: A
}

class RequiresAnyRef[A <: AnyRef] {
  def value: A
}

class RequiresBothManifestAndAnyRef[A <: AnyRef: Manifest] {
  def value: A
}

Is this possible ? Alternatively can a 'BoundedFunctor trait be defined ? something like this:

trait BoundedFunctor[F[_], Bound[_]] {
  def fmap[A: Bound, B: Bound](r: F[A], f: A => B): F[B]
}

Here's my motivating example: How can I defined a Functor for the class TypedConverter.

import com.thoughtworks.xstream.converters.Converter

abstract class TypedConverter[A <: AnyRef: Manifest] extends Converter { 
  final def canConvert(klass: Class[_]) = 
    manifest[A].erasure.isAssignableFrom(klass)

  final def marshal(value: AnyRef, writer: HierarchicalStreamWriter, 
                    context: MarshallingContext) =
    typedMarshal(value.asInstanceOf[A], writer, context)

  final def unmarshal(reader: HierarchicalStreamReader, 
                      context: UnmarshallingContext) = 
    typedUnmarshal(reader, context)

  def typedMarshal(value: A, writer: HierarchicalStreamWriter, 
                   context: MarshallingContext): Unit

  def typedUnmarshal(reader: HierarchicalStreamReader, 
                     context: UnmarshallingContext): A
}

This higher-kinded type has two constraints on its type parameter, first Manifest because that's used in the implementation of 'canConvert', second AnyRef because unmarshal requires an Object.

Actually I'm trying to create an InvariantFunctor, but Functor will do to start with.

1
I see. But one thing is still unclear for me: How should this Functor be used? Could you give a few examples what should work and what should not work?Christian
BoundedFunctor seems to do the trick for the first case, but I'm guessing the remainder require some implicit jiggerypokery.Stacy

1 Answers

2
votes

See, in Math, a functor is a mapping from one category to another. In Comp Sci somehow people believe a functor is an endofunctor, e.g. for Scala discourse, it is defined on all Scala types.

That's how scalaz's implementation is written.

But it does not have to be so. As I understand, in your case you have a subcategory (roughly defined by Bound); so the functor will be from Bound to Scala.

It is a good idea in general, not much explored. I believe we have to go investigate this further. It is a little bit problematic though to explicitly define categories in programming languages. Not even sure about Agda.