Note that there are some explanatory texts on larger screens.

plurals
  1. PODefining lift for all mappable types
    text
    copied!<p>For the sake of my own curiosity, I tried to define Haskell's <code>liftM</code> for all types that define <code>map[B](f : A =&gt; B): M[A]</code>, but couldn't get there on my own*. I was hoping that somebody with a deeper insight into Scala's type system might be able to explain it to me.</p> <p>First I attempted to use structural type constraints:</p> <pre><code>import language.higherKinds import language.reflectiveCalls def lift[A, B, F[_] &lt;: {def map(f : A =&gt; B): F[B]}](a : F[A])(g : A =&gt; B) = a map g lift(Some(1)) {_ + 1} // error: inferred type arguments [Int,Nothing,Some] do not // conform to method lift's type parameter bounds // [A,B,F[_] &lt;: AnyRef{def map(f: A =&gt; B): F[B]}] </code></pre> <p>I've attempted a few other things in this vein, but could never get a function to accept a type defining <code>map[B](f : A =&gt; B): F[B]</code>. I also took a whack at it via traits:</p> <pre><code>object Liftable { import language.higherKinds trait Mappable[A, F[_]] { def map[B](f : A =&gt; B): F[B] } implicit class MappableOption[A](opt : Option[A]) extends Mappable[A, Option] { def map[B](f : A =&gt; B) = opt map f } def lift[A, B, F[_]](a : Mappable[A, F])(f : A =&gt; B) = a map f } import Liftable._ lift(Some(1)) {_ + 1} // Some(2) lift(None:Option[Int]) {_ + 1} // None </code></pre> <p><strong>This works</strong>, <em>but</em> it would require defining an implicit class for <em>every</em> type that defines the <code>map</code> function. It loses a lot of it's usefulness there. I'm not sure if there's a way to define an implicit conversion for all types that define <code>map</code> - it brings me back to the problem I had with my first approach.</p> <p>Am I overlooking something? Is the only viable way to do this to follow the second approach, and define an implicit conversion for each mappable type individually?</p> <hr> <p><sub> * I'm aware that the <em>Scalaz</em> library has some form of the <code>lift</code> function defined for its <code>Functor</code> trait, but I wasn't fully able to understand how it works in context with their entire library just by glancing through the source code. </sub></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload