#scala #functional-programming #functor #trampolines
#scala #функциональное программирование #функтор #батуты
Вопрос:
Я пытаюсь продемонстрировать батут [ A] как функтор (т. Е. Предоставляет map[B](f: A = > B)). Я понимаю классическую реализацию Trampoline как монады, как описано в Stackless Scala .
Однако, есть ли способ реализовать функцию map (а не flatMap) только с помощью Done и других подклассов Trampoline, или мне нужно также добавить подкласс Flatmap?
Ответ №1:
Вы не можете вызвать Trampoline представляет собой вычислительный процесс. Функтор дает вам map
функцию, которая может преобразовать только ваше конечное значение, но порождать новое вычисление — это работа монады, которая каким-то образом абстрагируется от процесса вычисления с flatMap
помощью операции (хотя я определенно предпочитаю bind
имя Haskell, потому что оно лучше обозначает фактическую семантику операции). Таким образом, с помощью функторов вы не можете объединять разные части вычислений вместе, например, в scalaz Trampoline — это псевдоним для свободной монады, которая определяет map следующим образом:
def map[B](f: A => B): Free[S, B] =
flatMap(a => Return(f(a)))
Как вы можете видеть, он только преобразует значение, но не добавляет новый шаг, чего вы хотите достичь с помощью батутов.
Комментарии:
1. Итак, если я хочу показывать только хвостовые вызовы (без map, flatmap), я могу использовать Done и многое другое, но, добавив «map», я должен ввести подкласс Flatmap. Я думал, что это нужно только для поддержки flatMap
2. У меня было ощущение, что для поддержки «map» это можно было бы сделать каким-то образом, используя только Done и многое другое.
3. @ShimiBandiel ты можешь. Но идея заключается в том, что вы выполняете вычисления, и этот шаг выполняется с помощью
flatMap
, и именно поэтомуmap
операция определяется сflatMap
помощью , не как простое преобразование, а преобразование, выполняемое на новом шаге.4. Я пытался это реализовать, но я всегда получаю исключение StackOverflowException без добавления подкласса Flatmap. Причина, по которой я пытаюсь это сделать, заключается в презентации. Начните с простых завершающих вызовов, используйте Done и многое другое, покажите «map», а затем перейдите к flatMap и подклассу Flatmap. Но, похоже, я не могу реализовать «map» без подкласса Flatmap. И для большинства монад я могу показать постепенный шаг в реализации между «Функтором» и «Монадой».
5. @ShimiBandiel Вы можете реализовать map просто tramp match { case Done(v) => f(v) case More(thunk) => f(thunk())} , но это f(thunk()) в больших случаях просто f(() => f(() => f (() => f (v))))), это причина, по которой вы получаете SOE.
FlatMap
разбивает эту цепочку на более мелкие шаги, если у нас есть значение (выполненный случай), то мы продолжаем вычисление следующим шагом, если у нас больше шагов (больше случая), мы вычисляем его, а затем используемFlatMap
. В своей презентации вы можете начать с простогоMap
, показать, что он вызывает SOE, затем показать, что это монада, а flatMap — это решение