Scalaz 7 how to use Functor with Function1

273 views Asked by At

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)
2

There are 2 answers

5
Mario Galic On BEST ANSWER

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)
0
MaatDeamon On

I accepted the answer above because it solves the problem. It shows how to do what i wanted to do. Making a function a functor explicitly so as to map on it. However i was left a bit unsatisfied as to why i have to do this ({type F[B] = Int => B})#F for function ? why it can't be fully generic, why the library does not provide that out of the box, instead of having the user do it.

I believe I have found the answer in the following posts:

What are type lambdas in Scala and what are their benefits?

Why type lambdas?

Based on it I concluded that the library can not bake that for you whenever you do not have F[X] such as F[Int, INT] or Map[Int, INT]. One need to manually resort to Type lambdas which forces you to do something partial. Hence we can't have something generic baked in the library for FunctionX.