Hone logo
Hone
Problems

Delimited Continuations with Typescript

Delimited continuations allow a function to "capture" its remaining execution context and pass it to another function, enabling powerful control flow manipulation. This challenge asks you to implement a basic system for delimited continuations in Typescript, focusing on type safety and using generics to ensure the continuation type is correctly inferred. This is useful for implementing things like exception handling, coroutines, and advanced control flow patterns in a type-safe manner.

Problem Description

You need to create a generic DelimitedContinuation type and a function createDelimitedContinuation that allows you to capture and resume a portion of a function's execution. The DelimitedContinuation type should represent a function that takes a single argument of a specific type (K) and returns a value of another specific type (V). The createDelimitedContinuation function should accept a continuation delimiter (D), a function to execute (fn), and return a DelimitedContinuation<K, V>. The fn will be executed until it calls the continuation with a value of type D. The continuation then resumes execution from where it left off, passing the value provided to the continuation.

Key Requirements:

  • Type Safety: The continuation type DelimitedContinuation<K, V> must be correctly inferred based on the types used within the function fn.
  • Delimiter Handling: The function fn must terminate when it calls the returned DelimitedContinuation with a value of type D.
  • Resumption: After the continuation is called, the execution of fn must resume from the point immediately after the continuation call.
  • Generic Types: K represents the type of the argument passed to the continuation, and V represents the type returned by the continuation.

Expected Behavior:

The createDelimitedContinuation function should return a function that, when called with a value of type D, will resume the execution of the original function fn with that value. The original function fn should behave as if the continuation call was a normal function call.

Edge Cases to Consider:

  • What happens if the function fn never calls the continuation? (The function should return without error, but without producing a result.)
  • What happens if the function fn calls the continuation multiple times? (The behavior is undefined, but the code should not crash.)
  • What happens if the value passed to the continuation is not of type D? (The code should not crash, but the continuation should not resume.)

Examples

Example 1:

Input:
const delimiter = "done";
const fn = (x: number) => {
  console.log("Processing:", x);
  return createDelimitedContinuation(delimiter, (y: string) => {
    console.log("Continuation called with:", y);
    return x + 1;
  });
};

Output:
// When fn(5) is called:
// Processing: 5
// Continuation called with: done
// Returns: 6

Explanation: fn is called with 5. It logs "Processing: 5". Then, it calls the continuation with "done". The continuation logs "Continuation called with: done" and returns 6.

Example 2:

Input:
const delimiter = "result";
const fn = (x: string) => {
  console.log("Starting with:", x);
  const continuation = createDelimitedContinuation(delimiter, (y: number) => {
    console.log("Received result:", y);
    return y * 2;
  });
  return continuation("hello");
};

Output:
// When fn("initial") is called:
// Starting with: initial
// Received result: NaN
// Returns: NaN

Explanation: fn is called with "initial". It logs "Starting with: initial". It creates a continuation that expects a number and doubles it. It then calls the continuation with "hello", which is converted to NaN. The continuation logs "Received result: NaN" and returns NaN.

Example 3: (Edge Case - No Continuation Call)

Input:
const delimiter = "end";
const fn = (x: number) => {
  console.log("Doing some work:", x);
  return x * 2;
};

const continuation = createDelimitedContinuation(delimiter, fn);

Output:
// When continuation(10) is called:
// Doing some work: 10
// Returns: 20

Explanation: The function fn never calls the continuation. The continuation is called with 10, but it does nothing, and the function returns its original value.

Constraints

  • The delimiter D must be a primitive type (string, number, boolean, symbol, or bigint).
  • The function fn must be a function that accepts any number of arguments and returns a value.
  • The createDelimitedContinuation function must be able to handle any valid Typescript function.
  • Performance should be reasonable for typical use cases. Avoid unnecessary allocations.

Notes

  • This is a simplified implementation of delimited continuations. A full implementation would require more sophisticated type manipulation and potentially runtime support.
  • Consider using a type predicate to ensure that the value passed to the continuation is of the correct type.
  • Think about how to handle the context of the function fn when creating the continuation. You'll need to capture the necessary state to resume execution correctly.
  • The core challenge is to create a type that correctly represents the continuation and a function that can capture and resume the execution context.
Loading editor...
typescript