Scalaz 7 как использовать Functor с Function1

Привет, я начинаю изучать Scalaz.

Я хочу получить функцию и сопоставить ее с другой функцией.

хотя я могу написать это:

import scalaz._, Scalaz._

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

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

и это работает, когда я использую явный подход в соответствии с примерами в проекте github, он не работает (см. Ниже)

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}

я получаю как ошибку

Ошибка: (10, 17) Function1 принимает два параметра типа, ожидаемых: один Functor[Function1].map{x:Int => x * 4}{(x:Int) =>x * 7}

Я вдохновился примером в документе, который работает

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

person MaatDeamon    schedule 04.05.2019    source источник


Ответы (2)


Расширяя имплициты ((x: Int) => x * 4) map ((x: Int) => x * 7), мы получаем

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

Подпись function1Covariant< / а> это

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

в то время как подпись Functor.apply это

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

Замена F[_] на ({type F[B] = Int => B})#F или использование kind-projector с помощью Int => ? мы делаем apply require неявным

Functor[Int => ?]

что удовлетворяет function1Covariant[Int]: Monad[Int => ?], так как Monad является типом Functor. Таким образом, мы могли бы написать явно

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

или используя вид-проектор как

Functor[Int => ?].map((x: Int) => x * 4)((x: Int) => x * 7)
person Mario Galic    schedule 04.05.2019
comment
Спасибо, это имеет смысл. В то же время я пытаюсь изучить библиотеку scalaz, узнать, как она устроена и где что находится с точки зрения пакета, и как собрать разные части вместе, чтобы получить то, что вы хотите. Так что в некотором смысле я хочу понять логику. Почему моя версия, которая явно не использует Functor, работала, а не та, которая использовала его явно? Каким-то образом Functor поддерживает FunctionN, но не так, как можно было бы ожидать, интересно, почему? Или я что-то упускаю? - person MaatDeamon; 04.05.2019
comment
Последние версии Scala поддерживают частичную унификацию конструкторов типов. Поэтому, когда вы позволяете компилятору выводить типы, он может вывести что-то эквивалентное ({type F[B] = Int => B})#F. - person Jasper-M; 04.05.2019
comment
Понятно. Но тогда почему нет класса типов для FunctionN, как для Option, который я получаю из std.option._, и чем тогда хорош std.function._? - person MaatDeamon; 04.05.2019
comment
Думаю, я был не совсем точен. Компилятор может вывести это даже без частичной унификации. В любом случае, дело в том, что тип, который вы указали явно, был неправильным, но компилятор может сделать правильный вывод, поэтому ваша первая версия работала. - person Jasper-M; 04.05.2019
comment
Я думаю, что получил ответ на свой вопрос после проверки немного stackoverflow и прочего. Пожалуйста, можете ли вы подтвердить, что я правильно понимаю? Это ограничение scala, которое делает его чем-то, что нельзя заранее запечь в библиотеке. - person MaatDeamon; 04.05.2019

Я принял ответ выше, потому что он решает проблему. Он показывает, как сделать то, что я хотел сделать. Явно сделать функцию функтором, чтобы отображать ее. Однако я остался немного недоволен тем, почему я должен делать это ({type F[B] = Int => B})#F для функции? почему это не может быть полностью универсальным, почему библиотека не предоставляет это из коробки, вместо того, чтобы это делал пользователь.

Я считаю, что нашел ответ в следующих сообщениях:

Что такое лямбда-выражения типов в Scala и каковы их преимущества?

Зачем вводить лямбда-выражения?

Основываясь на этом, я пришел к выводу, что библиотека не может испечь это для вас, если у вас нет F[X], например F[Int, INT] или Map[Int, INT]. Нужно вручную прибегнуть к Type lambdas, что заставляет вас делать что-то частичное. Следовательно, мы не можем запечь что-то универсальное в библиотеке для FunctionX.

person MaatDeamon    schedule 04.05.2019