Scalaz: how `scalaz.syntax.applicative._` magic works

This question is related to this , where I was trying to figure out how to use the reader monad in Scala.

In the response, the author uses the following code to get the instance ReaderInt[String]:

import scalaz.syntax.applicative._
val alwaysHello2: ReaderInt[String] = "hello".point[ReaderInt]

What mechanisms "hello".point[ReaderInt]does Scala use to resolve an expression type , so that it uses the correct function point?

+4
source share
2 answers

A good first step anytime you are trying to find something like this is to use the reflection API to bleach the expression:

scala> import scalaz.Reader, scalaz.syntax.applicative._
import scalaz.Reader
import scalaz.syntax.applicative._

scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}

scala> type ReaderInt[A] = Reader[Int, A]
defined type alias ReaderInt

scala> showCode(reify("hello".point[ReaderInt]).tree)
res0: String = `package`.applicative.ApplicativeIdV("hello").point[$read.ReaderInt](Kleisli.kleisliIdMonadReader)

( scala.reflect.runtime , .)

, .point[ReaderInt] , point - String - , String , point ( "" Scala). showCode , , , , ApplicativeIdV applicative .

String, ApplicativeIdV[String]. point :

def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)

- :

def point[F[_]](implicit F: Applicative[F]): F[A] = F.point(self)

, , , applicative F. , F ReaderInt. Reader[Int, _], Kleisli[Id.Id, Int, _] .

, , Kleisli, , Kleisli, showCode , Kleisli.kleisliIdMonadReader. , ReaderInt[String], .

+11

, , .

scalaz.syntax

point, .

point ( haskell return) pure ( ) Applicative. - F, F Applicative.

, .

val

implicit val KA = scalaz.Kleisli.kleisliIdApplicative[Int]

scala Int . , , Reader ( )

import scalaz.std.option.optionInstance 
import scalaz.std.list.listInstance

..

, . point . :

1. :

scalaz.std.option.optionInstance.point("hello")
KA.pure("hello")

2. :

Applicative[Option].point("hello") 

,

object Applicative {
  @inline def apply[F[_]](implicit F: Applicative[F]): Applicative[F] = F
}

apply Applicative[F] F.

, Applicative[Option].point("hello")   Applicative[Option].apply(scalaz.std.option.optionInstance) optionInstance

3.

import scalaz.syntax.applicative._ 

:

  implicit def ApplicativeIdV[A](v: => A) = new ApplicativeIdV[A] {
    val nv = Need(v)
    def self = nv.value
  }

  trait ApplicativeIdV[A] extends Ops[A] {
    def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)
    def pure[F[_] : Applicative]: F[A] = Applicative[F].point(self)
    def η[F[_] : Applicative]: F[A] = Applicative[F].point(self)
  }  ////

, , point String

"hello".point[Option] 

, String point implicits, -, point, String.

, String ApplicativeIdV[String], point:

 def point[F[_] : Applicative]: F[A] = Applicative[F].point(self)

, - desugares

new ApplicativeIdV[Option]("hello")


scalaz . sequence

def sequence[G[_]: Applicative, A](fga: F[G[A]]): G[F[A]] =
    traverse(fga)(ga => ga)

G , Applicative[G] . , :

def sequence[G[_], A](fga: F[G[A]])(implicit ev: Applicative[G[_]]): G[F[A]] =
        traverse(fga)(ga => ga)

, , , [G] [F].

import scalaz.std.list.listInstance
import scalaz.std.option.optionInstance
Traverse[List].sequence[Option, String](Option("hello"))
+4

Source: https://habr.com/ru/post/1648776/


All Articles