Почему мы не можем предоставить неявный класс типов, когда тип ковариантен? - PullRequest
0 голосов
/ 30 мая 2018

Я проектирую свой алгебраический тип данных и столкнулся с проблемой отключения неявного класса типов.Вот что у меня есть:

sealed abstract class Stream[+F[_], +T] {
  def run()(implicit M: Monad[F]): F[Unit] = Stream.run(this)
}

object Stream{
  final case object Halt extends Stream[Nothing, Nothing]
  private def run[F[_], T](stream: Stream[F, T])(implicit M: Monad[F]): F[Unit] = stream match {
    case Halt => M.pure()
  }
}

Я получил ошибку компиляции

Error:(10, 22) covariant type F occurs in invariant position in type 
     Monad[F] of value M def run()(implicit M: Monad[F]): F[Unit] = M.pure()

Я сделал ее ковариантной, чтобы иметь возможность возвращать Halt extends Stream[Nothing, Nothing] без приведения, но все же мне нужно Monad[F] класс типов для использования его операции для предоставленного контекста F[_].Каким было бы решение в этом случае?

1 Ответ

0 голосов
/ 30 мая 2018

Это скомпилируется, только если Monad был против -вариант.В противном случае у вас есть:

val stream: Stream[Nothing, Nothing] = Halt
val stream1: Stream[Maybe, Int] = stream // by covariance
val x = stream1.run()(implicitly[Monad[Maybe]])

, но Halt.run принимает только Monad[Nothing], поэтому Monad[Maybe] должен быть подтипом Monad[Nothing].

Что бырешение в этом случае?

Не определять run как это?Как правило, поскольку скалязы и кошки решили сделать свои классы типов инвариантными, у вас возникнут проблемы при попытке использовать их в со / контрвариантных типах.

...