Батут как функтор

#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 — это решение