/ / `назавжди` Комбінатор з вищим типом - масштаб

"завжди" Комбінатор з вищим Kinded Kind - скала

Я намагаюся запустити наступного комбінатора з Функціональне програмування в Scala:

trait AddlCombinators[F[_]] extends Monad[F[_]] {
def forever[A, B](a: F[A]): F[B] = {
lazy val t: F[B] = forever(a)
a flatMap (_ => t)
}
}

Але це не компілюється:

[error] AddlCombinators.scala:7: value flatMap is not a member of type
parameter F[A]
[error]     a flatMap (_ => t)
[error]       ^

Я розумію, що мені потрібно користуватися F[_] як це позначає вищий тип роду.

Наприклад, я написав а Monad[List] в минулому розділі цієї книги:

object ListMonad extends Monad[List] {
def unit[A](a: => A): List[A] = List(a)

def flatMap[A,B](ma: List[A])(f: A => List[B]): List[B] =
ma.map(x => f(x)).flatten
}

РЕДАГУВАТИ Додавання Monad і Functor код

trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}

trait Monad[F[_]] extends Functor[F] {
def unit[A](a: => A): F[A]
def flatMap[A,B](ma: F[A])(f: A => F[B]): F[B]

Як я можу вирішити вказану вище помилку компіляції? Також, у чому сенс F[_] як тип до AddlCombinators і Monad? Чи можна використовувати загальний "тип вищого роду"?

Відповіді:

2 для відповіді № 1

a flatMap (_ => t) є винуватцем тут.

Відповідно до наведеного коду, ви можете використовувати flatMap(a)(_ => t) щоб скласти його.

Інтерфейс Monad не автоматично додає монадійних операторів до будь-якого параметру, якщо ви не використовуєте імпліцити.

F[_] це екзистенційний тип, який означає, що F - тип, який містить якийсь інший тип, еквівалентний: trait F {type A}. Кожна монада є функтором, і лише параметризовані типи можуть бути функторами, тому вам потрібно параметризувати Monads за допомогою F[_]. Інакше кажучи, лише параметризовані типи можуть задовольнити інтерфейс Monad / Functor. Тип, параметризований параметризованим типом (* -> *) -> * - тип вищого роду. F[_] є найменш обмежуючим, отже, найбільш загальним типомякі можна використовувати тут. Інші параметризовані типи можна зробити так, щоб вони виглядали як F [_] за допомогою проекцій типу. Наприклад, щоб визначити монаду для упередженого праворуч типу типу, ви можете використовувати type FA = ({type l[a] = Either[L, a]})#l як F[_]. Побачити тут повний код для Monad for Either.