@ Jwvh предоставил более программный ответ, но я хочу копнуть немного глубже.
Я, конечно, ценю, что вы пытаетесь понять, как все работает в Scala, однако, если вы действительно хотите копнуть так глубоко, я боюсь, что вам нужно будет получить некоторые базовые знания теории категорий, поскольку за этим нет "идеи"поднятие в скале », но просто« идея поднятия »
Вот почему такие функции, как« карта », могут быть очень запутанными. По сути, программистов учат отображать и т. Д. Как операции над коллекциями, где они фактически являются операциями, которые идут с Функторами и Естественными Преобразованиями (это обычно упоминается как fmap в теории категорий, а также на Haskell).
Прежде чем я продолжу, краткий ответ - это сопоставление с образцом в приведенных вами примерах, а в некоторых из них это оба. Карта определена специально для случая, единственное условие - она поддерживает functoriality
Внимание: я не буду определять каждый отдельный термин ниже, так как мне нужно написатьКнига, чтобы построить некоторые из следующих определений, заинтересованные читатели могут исследовать их самостоятельно. Вы должны быть в состоянии получить некоторое базовое понимание, следуя типам
Давайте рассмотрим их как Функторы, определение будет примерно таким:
В (очень очень)Короче говоря, мы рассматриваем типы как объекты в категории нашего языка. Функции между этими типами (конструкторы типов) представляют собой морфизмы между типами в этой категории. Множество этих преобразований называются эндофункторами (заберите нас из категории Scala и верните в категорию Scala). Функторы должны иметь полиморфную (которая на самом деле имеет совершенно другое (дополнительное) определение в теории категорий) функцию карты, которая возьмет некоторый объект A, через конструктор типов превратит его в объект B.
implicit val option: Functor[Option] = new Functor[Option] {
override def map[A,B](optA: Option[A])(f: (A) => B): Option[B] = optA match{
case Some(a) => Some(f(a))
case _ => None
}
}
implicit val seq: Functor[Seq[_]] = new Functor[Seq[_]] {
override def map[A,B](sA: Seq[A])(f: (A) => B): Seq[B] = sA match{
case a :: tail => Seq(f(a), map(tail)(f))
case Nil => Nil
}
}
Как вы можете видеть во втором случае, есть и то, и другое (скорее рекурсия, чем итерация, но все же).
Теперь, прежде чем интернет взорвется, я скажу, что вы не можете сопоставить шаблон сСек в Скала. Это работает здесь, потому что по умолчанию Seq также является списком. Я просто привел этот пример, потому что он проще для понимания. Базовое определение что-то вроде этого.
Теперь подождите секунду. Если вы посмотрите на эти типы, вы увидите, что для них также определен flatMap. Это означает, что они являются чем-то более особенным, чем простые функторы. Это монады. Таким образом, помимо удовлетворения функториальности, они подчиняются монадическим законам.
Оказывается, у Monad есть другое значение в базовой scala, подробнее об этом здесь: Что именно делает Option монадой в Scala?
Но, опять же, очень оченьКороче говоря, это означает, что мы сейчас находимся в категории, где эндофункторы из нашей предыдущей категории являются объектами, а отображения между ними - морфизмы (естественные преобразования), это немного более точно, потому что, если вы подумаете об этом, когда вы берете тип итрансформируя его, вы берете (переносите) все его внутренние конструкторы типов (2-элементные или внутренние морфизмы) вместе с ним, вы не только берете эту единственную идею типа без его функций.
implicit val optionMonad: Monad[Option] = new Monad[Option] {
override def flatMap[A, B](optA: Option[A])(f: (A) => Option[B]): Option[B] = optA match{
case Some(a) => f(a)
case _ => None
}
def pure[A](a: A): Option[A] = Some(a)
//You can define map using pure and flatmap
}
implicit val seqMonad: Monad[Seq[_]] = new Monad[Seq[_]] {
override def flatMap[A, B](sA: Seq[A])(f: (A) => Seq[B]): Seq[B] = sA match{
case x :: xs => f(a).append(flatMap(tail)(f))
case Nil => Nil
}
override def pure[A](a: A): Seq[A] = Seq(a)
//Same warning as above, also you can implement map with the above 2 funcs
}
Одна вещь, на которую вы всегда можете рассчитывать, это карта, имеющая совпадение с шаблоном (или некоторая инструкция if). Почему? Чтобы удовлетворить законы идентичности, нам нужно иметь своего рода «базовый случай», объект-единицу и во многих случаях (например, списки) эти типы будут тем, что мы называем продуктом или копроизведением.
Надеюсь, это вас не смутило. Я бы хотел вникнуть в каждую деталь этого, но это просто заняло бы страницы, я настоятельно рекомендую разбираться в категориях, чтобы полностью понять, откуда они берутся.