scalascalazscalaz7

Scalaz 7 how to use Functor with Function1


Hi i am starsting to learn Scalaz.

I want to get a function and map over it with another function.

although i am able to write this:

import scalaz._, Scalaz._

import std.function._
import syntax.monad._

((x: Int) => x + 1) map {_ * 7}

and it works, when i use the explicit appraoch as per the examples in github project it does not work (see below)

import scalaz._, Scalaz._

import std.option._
import std.function._
import syntax.monad._

Functor[Function1[Int,Int]].map{x:Int => x * 4}{(x:Int) =>x * 7}

I get as error

Error:(10, 17) Function1 takes two type parameters, expected: one Functor[Function1].map{x:Int => x * 4}{(x:Int) =>x * 7}

I did inspired myself from an example in the doc that works

Functor[Option].map(Some("adsf"))(_.length)

Solution

  • Expanding implicits of ((x: Int) => x * 4) map ((x: Int) => x * 7) we get

    ToFunctorOps(((x: Int) => x * 4))(function1Covariant) map ((x: Int) => x * 7)
    

    Signature of function1Covariant is

    implicit def function1Covariant[T]: Monad[T => ?] with ...
    

    whilst signature of Functor.apply is

    def apply[F[_]](implicit F: Functor[F]): Functor[F] = F
    

    Substituting F[_] with ({type F[B] = Int => B})#F, or using kind-projector with Int => ?, we make apply require implicit

    Functor[Int => ?]
    

    which is satisfied by function1Covariant[Int]: Monad[Int => ?] since Monad is a type of Functor. Thus we could write explicitly

    Functor[({type F[B] = Int => B})#F].map((x: Int) => x * 4)((x: Int) => x * 7)
    

    or using kind-projector as

    Functor[Int => ?].map((x: Int) => x * 4)((x: Int) => x * 7)