Hone logo
Hone
Problems

Proof-Carrying Code Types in TypeScript: Safe Data Transformation

Proof-carrying code types (PCC) aim to ensure that code can only execute if it can prove it adheres to a specific type contract. This challenge explores a simplified implementation of PCC in TypeScript, focusing on data transformation. You'll create a system where a function can provide a "proof" alongside its code, and a "verifier" can check if the proof guarantees the function's output type matches the expected type. This is a foundational concept for enhanced type safety and runtime verification.

Problem Description

You are tasked with building a basic PCC system in TypeScript. The core components are:

  1. Transformer Interface: Defines a function type that takes an input of type A and returns a value of type B.
  2. Proof Interface: Represents a proof that a Transformer function will always produce an output of a specific type. For this challenge, the Proof will be a simple string describing the transformation.
  3. Verifier Function: Takes a Transformer, a Proof, and an input value of type A. It checks if the Proof is valid (in this simplified case, just a non-empty string). If the proof is valid, it executes the Transformer with the input and returns the result. If the proof is invalid, it throws an error.
  4. createTransformerWithProof Function: This function takes a Transformer and a Proof and returns an object containing both. This allows you to bundle the code and its proof together.

The goal is to create a system where the Verifier can confidently execute the Transformer knowing that the Proof guarantees the output type. This is a simplified model, but it demonstrates the core idea of PCC.

Examples

Example 1:

Input:
Transformer: (x: number) => x * 2
Proof: "Multiplies by 2"
Input Value: 5

Output: 10
Explanation: The proof "Multiplies by 2" is valid (non-empty string). The transformer (x => x * 2) is executed with input 5, resulting in 10.

Example 2:

Input:
Transformer: (x: string) => x.toUpperCase()
Proof: "" // Invalid Proof
Input Value: "hello"

Output: Error: Invalid Proof: Proof must be a non-empty string.
Explanation: The proof is an empty string, which is considered invalid. The Verifier throws an error.

Example 3: (Edge Case - Type Mismatch)

Input:
Transformer: (x: number) => "string" // Type mismatch - should return number
Proof: "Returns a number"
Input Value: 10

Output: "string"
Explanation: While the proof is valid, the transformer *still* returns a string.  This demonstrates that the PCC system, in this simplified form, doesn't prevent type mismatches within the transformer itself.  It only verifies the proof's claim about the *output* type.

Constraints

  • The Proof must be a non-empty string. An empty string signifies an invalid proof.
  • The Transformer function must be a function that accepts a single argument and returns a value.
  • The Verifier function must throw an error if the Proof is invalid.
  • The createTransformerWithProof function should return an object with transformer and proof properties.
  • No external libraries are allowed.

Notes

  • This is a simplified implementation of PCC. Real-world PCC systems involve much more complex proofs and verification mechanisms.
  • Focus on the core concepts of bundling code and proofs and verifying the proof before execution.
  • Consider how you might extend this system to handle more complex types and proofs in the future.
  • The "type mismatch" edge case in Example 3 highlights a limitation of this simplified approach. A more robust PCC system would ideally prevent such mismatches. However, for this challenge, focus on the proof verification aspect.
  • Think about how you could represent different types of proofs (e.g., proofs about the range of values a function can return).
Loading editor...
typescript