Profunctor Basics
Tutorial Video
Text description (accessibility)
This video demonstrates the "Profunctor Basics" functional Rust example. Difficulty level: Expert. Key concepts covered: Functional Programming. A profunctor is a type constructor `P<A, B>` that is contravariant in `A` and covariant in `B`. Key difference from OCaml: 1. **Variance**: Profunctors have a two
Tutorial
The Problem
A profunctor is a type constructor P<A, B> that is contravariant in A and covariant in B. Functions fn(A) -> B are the canonical profunctor: you can pre-map the input (A -> A' gives P<A', B>) and post-map the output (B -> B' gives P<A, B'>). Profunctors generalize both Functor (covariant only) and Contravariant (contravariant only). They are the mathematical foundation of the profunctor optics encoding (Van Laarhoven generalization).
🎯 Learning Outcomes
dimap: (A' -> A, B -> B') -> P<A, B> -> P<A', B'>fn(A) -> B as the canonical profunctorStrong and ChoiceCode Example
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Key Differences
Strong profunctors, prisms are Choice profunctors — the Van Laarhoven encoding selects the optic type via the profunctor class.pipes (streaming), profunctor-optics (Haskell), and data flow libraries.P: C^op × C -> Set is a functor from the product of a category and its opposite; functions are hom-sets, the canonical profunctor.OCaml Approach
OCaml's profunctor:
module type PROFUNCTOR = sig
type ('a, 'b) t
val dimap : ('c -> 'a) -> ('b -> 'd) -> ('a, 'b) t -> ('c, 'd) t
end
module FunctionProfunctor : PROFUNCTOR with type ('a, 'b) t = 'a -> 'b = struct
type ('a, 'b) t = 'a -> 'b
let dimap f g h = g >> h >> (fun x -> x) >> (fun _ -> failwith "") (* simplified *)
let dimap f g h x = g (h (f x))
end
OCaml's module system naturally expresses the profunctor abstraction. The lens and prism libraries use profunctors directly.
Full Source
#![allow(clippy::all)]
// Stub — awaiting conversion from OCaml source.Deep Comparison
OCaml vs Rust: Profunctor Basics
Overview
See the example.rs and example.ml files for detailed implementations.
Key Differences
| Aspect | OCaml | Rust |
|---|---|---|
| Type system | Hindley-Milner | Ownership + traits |
| Memory | GC | Zero-cost abstractions |
| Mutability | Explicit ref | mut keyword |
| Error handling | Option/Result | Result<T, E> |
See README.md for detailed comparison.
Exercises
lmap and rmap for the function profunctor in terms of dimap.Parser<A, B> profunctor where A is the input type and B is the output: dimap transforms inputs before parsing and outputs after.Strong for the function profunctor: first: P<A, B> -> P<(A, C), (B, C)>.