Я недавно написал ETL, который работает просто отлично.Я хотел бы напомнить себе, как использовать бесплатные монады, поэтому хотел бы конвертировать мой ETL как таковой.Примечание: мое намерение здесь не в том, чтобы написать лучший ETL, а в том, чтобы заново ознакомиться с бесплатными монадами.Пересматривая, как работают бесплатные монады, я получил возможность отследить тему этого вопроса.
Итак, я задал связанный вопрос несколько месяцев назад.Кто-то заметил, что мою рекурсивную функцию можно сделать хвостовой рекурсией, используя стиль передачи продолжения.Я не могу понять, как это сделать.
Пример кода:
type In1 = int
type In2 = int
type Out1 = int
type Out2 = int
type FaceInstruction<'a> =
| Member1 of (In1 * (Out1 -> 'a))
| Member2 of (In2 * (Out2 -> 'a))
let private mapI f = function
| Member1 (x, next) -> Member1 (x, next >> f)
| Member2 (x, next) -> Member2 (x, next >> f)
type FaceProgram<'a> =
| Free of FaceInstruction<FaceProgram<'a>>
| Pure of 'a
let rec bind f = function
| Free x -> x |> mapI (bind f) |> Free
| Pure x -> f x
Функция, которую я пытаюсь сделать так, чтобы хвост был восстановлен, это bind
Myпопытки выглядят примерно так:
let rec bind2 (f: 'a -> FaceProgram<'b>) k z : FaceProgram<'b> =
match z with
|Pure x -> x |> f |> k
|Free x -> bind2 ???
Я начинаю думать, что на самом деле невозможно сделать этот хвост рекурсивным.Тип FaceInstruction<'a>
уже включает в себя продолжение, а функция mapI
изменяет это продолжение, поэтому теперь попытка добавить другое продолжение k
является одним из двух дополнительных продолжений, которые я не могу обработать прямо сейчас!