Stacy
Stacy

Reputation: 41

How can scalaz' Functor be given a higher-kinded type with a context bound?

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.

Upvotes: 4

Views: 272

Answers (1)

Vlad Patryshev
Vlad Patryshev

Reputation: 1422

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.

Upvotes: 2

Related Questions