This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Implicits and 2.8.0.Beta-RC1

No replies
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
I'm having some trouble getting implicits to behave the way I want.  I think I may be playing with fire here, but I'm going to describe what I'm trying to do and hopefully someone can inform me the best way to go about it.


The goal is to have a monad M such that map/flatMap could return optimized monads, depending on how the types are transformed.  e.g.

val m : M[X] = ....

val x : MoptimizedForTraversable[X] - m.flatMap( x => createATraversable(x))

vs. normal

val y : M[Y] = m.flatMap(y => createMofY(x))

I'm also trying to attempt this feat with map (making the signatures harder...)




I'm trying to use the implicit tricks.  I have the following:

/**
 * This class encapsulates a method of ensuring a resource is opened/closed during critical stages of its lifecycle.
 */
trait M[+A] {

  /**
   * This method is used to immediately perform operations on a resource while it is open, ensuring the resource is
   * closed before returning.
   */
  def map[B, To](f : A => B)(implicit translator : CanSafelyTranslate[B,To]) : To
  def flatMap[B, To](f : A => B)(implicit translator : CanSafelyTranslate[B,To]) : To
  ...

}

/**
 * This trait's existence signifies that a ManagedResource can be converted into a ManagedTraversable safely or needs to remaining inside the monad.
 */
trait CanSafelyTranslate[-MappedElem, +To] {
  /**
   * This method takes a managed resource and a mapping function and returns a new result (inside/outside the managed resource).
   */
  def apply[T](from : M[T],  converter : T => MappedElem) : To
}


I then define my implict hierarchy as so:

trait LowPriorityImplictsForM {
  implicit def default[B] = new CanSafelyTranslate[B, GenericM[B]] {
    def apply[A](from : M[A],  converter : A => B) : GenericM[B] =  ...
  }
}
trait HighPriorityImplicitsForM {
   /** Assumes any mapping function to an iterator type creates a "traversable" */
  implicit def convertToTraversableM[A] = new CanSafelyTranslate[Traversable[B], MoptimizedForTraversable[B]] {
     def apply[A](from : M[A],  converter : A => Traversable[B]) : MoptimizedForTraversable[B] = ..
  }

  /** Assumes any mapping can remain in monad */
  implicit def stayMAndFlatten[B] = new CanSafelyTranslate[M[B], M[B]] {
      def apply[A](from : ManagedResource[A],  converter : A => M[B]) : M[B] = ...
  }
}

object M extends HighPriorityImplicitsForM {
  ... 
}



The issues I have are as follows:

1) map and flatMap behave the same. I want flatMap to be the only one to see the "stayMAndFlatten" implicit.  I was thinking about doing this with a superclass of CanSafelyTranslate.   flatMap would use this superclass, and map would not.  Then the implicit should only override when using flatMap.  I still have a few other wonky issues to work about before doing this, and a lot more testing to make sure things compile/type the way I desire before going about that.   Anyone have any ideas here?

2) you have to *explicitly* import M._ for these implicits to show up at all.   They are not found simple by virtual of the type being an M.  Is this by design of implicits, or does the curried function mean that it's looking in one of the Function objects for implicits instead of in M?


This entire design is an attempt to see if I can "Do The Right Thing(tm)" when using my monad with for loops and collections.  Anyway, I look forward to input!

thanks!
- Josh

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland