Немного терминологии:
- правильный тип (например, Int)
- тип первого порядка (например, Список [_]); мы могли бы также сказать первоклассный вид
- высший тип (например, Монада [M [_])
Когда ты говоришь
trait Monoid[A] {
def op(a1: A, a2: A): A
def zero: A
}
val listMonoid = new Monoid[List[Int]] {
def op(l: List[Int], l2: List[Int]) = List(1,2)
def zero = List(1,2)
}
вы параметризуете черту Monoid
с помощью некоторого типа A, который может (как вы заметили) быть простым типом, также известным как правильный тип (например, Int
) или параметризованный тип (например, List[Int]
или даже List[Set[Map[Int, Int]]
). Это делает Monoid
типом первого порядка. Мы также можем сказать, что это конструктор унарного типа - для создания окончательного типа требуется один тип.
В отличие от Monoid, некоторые абстракции (например, Monad) должны быть параметризованы конструктором типа. Int больше не работает. Это должен быть «какой-то тип, который может произвести другой тип». Абстракция, параметризованная конструктором типа (то есть параметризованная «типом первого порядка»), является типом более высокого порядка. Вот пример:
trait Monad[M[_]] {
def op[A, B](m: M[A], f: A => M[B]): M[B]
def zero[A](a: A): M[A]
}
object ListMonad extends Monad[List] {
def op[A, B](m: List[A], f: A => List[B]) = m.flatMap(f)
def zero[A](a: A) = List[A](a)
}
val listMonad = ListMonad.zero(42)
val result = ListMonad.op(listMonad, (i: Int) => List(i - 1, i, i + 1))
// result = List(41, 42, 43)
Итак, Monad
параметризуется типом первого порядка (конструктор унарного типа), что делает сам Monad
типом более высокого порядка.
Обратите внимание, что Monad
на самом деле не заботится о самом «внутреннем типе» на уровне класса, поскольку он будет определяться методами op
и zero
. Вы также можете сказать trait Monad[M[A]]
и «исправить» тип A в точке определения класса ListMonad
(например, исправить его до Int), но тогда вы теряете гибкость (тогда ваш ListMonad
сможет построить и отобразить только List[Int]
и вы потребуется другой класс, скажем, для List[String]
).
Это отличается от моноида, который не относится к более высокородным типам; ему не нужен конструктор типа для создания типа. Если бы это было необходимо, у вас никогда не было бы, скажем, Monoid[Int]
, потому что Int не является конструктором типа.
Также обратите внимание, как я сказал, что Monad нужен конструктор типа унарный, то есть он принимает только один тип (в отличие, например, от Map, который принимает два). Конструкторы типов часто обозначаются звездочками и стрелками:
- унарный конструктор типа первого порядка -
* -> *
(он принимает единственный тип и производит окончательный тип, например Set)
- конструктор двоичного типа первого порядка
* -> * -> *
(конструктор двоичного типа принимает два типа для создания окончательного типа, например, Map)
- унарный тип более высокого порядка -
(* -> *) -> *
(для создания окончательного типа требуется один конструктор унарного типа, например, Monad)
и т.п.
Итак, тип первого порядка берет простой / конкретный / правильный тип и производит окончательный тип, тогда как тип более высокого порядка идет на один уровень выше; для создания окончательного типа требуется тип первого порядка.
РЕДАКТИРОВАТЬ:
Отвечая на ваш вопрос в части «редактировать»: Хорошо, я думаю, я знаю, что вас смущает. listMonoid
- это не тип, поэтому он не может быть типом более высокого порядка. Это метод. Monad[List[Int]]
- полностью разрешенный тип. Monad[F[A]]
тоже полностью решен. Однако Monad
сам по себе относится к типу более высокого порядка.
Позвольте мне провести параллель с функциями. Если у вас есть функция foo(x: Int)
, то вызовы функций, такие как foo(42)
или foo(someIntegerValue)
, приводят к конкретным значениям. Это аналог Monad[List[Int]]
и Monad[F[A]]
. Однако foo
сам по себе является функцией, так же как Monad
сам является конструктором типа.
Если foo
принимает простое значение (не функцию), это функция первого порядка; если он принимает или возвращает функцию, то это функция высшего порядка. То же самое с конструкторами типов. Если он принимает простой тип, это конструктор типа первого порядка. Пример: List
. Если требуется другой конструктор типа, это конструктор типа более высокого порядка (также известный как тип более высокого порядка). Пример: Monad
.
Не смешивайте разрешенные типы с конструкторами типов. Имеет смысл задуматься, является ли функция foo
старшей или нет; это зависит от его аргументов и типа возвращаемого значения. Но нет смысла думать, является ли foo(42)
высшим порядком или нет; это не функция, а приложение функции, результатом которого является значение. Monad[List[Int]]
- это не конструктор типа, а приложение конструктора типа List
к конструктору типа Monad
(который является более высоким порядком). Точно так же Monoid[List[Int]]
не является конструктором типа, а приложением типа List[Int]
к конструктору типа Monoid
(который является первым порядком). Конструкторы типов высшего порядка называются HKT. Нет смысла говорить о HKT и указывать на конкретный разрешенный тип (который был создан в результате применения некоторого конструктора типа).
person
slouc
schedule
17.04.2017