惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
IT之家
IT之家
博客园 - Franky
博客园_首页
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
量子位
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Jina AI
Jina AI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog RSS Feed

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Type Inhabitation in Lean: Why “Hello {name}” Can Become ...
Shrijith Ven · 2026-05-27 · via DEV Community

Hello, I'm Shrijith Venkatramana. I'm building git-lrc, an AI code reviewer that runs on every commit. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.


Most developers think of type systems as glorified linting.

  • string vs number
  • nullable vs non-nullable
  • maybe some autocomplete

But in Lean, a type can encode an actual logical property.

Not:

“this variable is a string”

but:

“this string is guaranteed to be non-empty.”

And once that guarantee exists, invalid states become literally unrepresentable.

This is where type inhabitation enters the picture.


1. What Does “Type Inhabitation” Mean?

A type is inhabited if you can construct a value of that type.

For example:

#check Nat

Enter fullscreen mode Exit fullscreen mode

Nat is inhabited because values like:

0
1
42

Enter fullscreen mode Exit fullscreen mode

exist.

Similarly:

#check True

Enter fullscreen mode Exit fullscreen mode

is inhabited because Lean has a proof of True.

But:

#check False

Enter fullscreen mode Exit fullscreen mode

is uninhabited.

There is no valid value of type False.

In Lean, programs and proofs collapse into the same thing:

Logic Programming
proposition type
proof value/program
proving constructing

So asking:

“Can this theorem be proven?”

becomes:

“Can this type be inhabited?”

That sounds abstract until you realize it applies directly to ordinary software.


2. The “Hello {name}” Problem

Suppose you write:

function greet(name: string) {
  return `Hello ${name}`
}

Enter fullscreen mode Exit fullscreen mode

What assumptions exist here?

Hidden ones:

  • name should not be empty
  • maybe it should be trimmed
  • maybe length-bounded
  • maybe validated UTF-8
  • maybe sanitized

But the type says only:

string

Enter fullscreen mode Exit fullscreen mode

So the real semantics live:

  • in comments,
  • conventions,
  • tribal knowledge,
  • or bugs.

In Lean, we can move the invariant into the type itself.


3. A String That Cannot Be Empty

Here’s a refined type:

structure NonEmptyString where
  value : String
  proof : value.length > 0

Enter fullscreen mode Exit fullscreen mode

This says:

A NonEmptyString consists of:

  1. a string value
  2. proof that the string length is greater than zero

Now this becomes impossible:

"", ?proof

Enter fullscreen mode Exit fullscreen mode

because no proof exists that:

"".length > 0

Enter fullscreen mode Exit fullscreen mode

So Lean rejects construction entirely.

That’s the key idea:

invalid states become uninhabitable.


4. But Real Programs Are Dynamic

At this point most developers ask:

“How can the compiler prove user input is non-empty?”

It usually cannot.

If the input comes from:

  • a form,
  • database,
  • API,
  • terminal,
  • environment variable,

then the value is only known at runtime.

So the trick is different.

We:

  1. validate dynamically once,
  2. convert into a stronger type,
  3. carry guarantees statically afterward.

This pattern is sometimes called:

Parse, don’t validate.


5. The Smart Constructor

Here’s the canonical approach:

def mkNonEmpty (s : String) : Option NonEmptyString :=
  if h : s.length > 0 then
    some s, h
  else
    none

Enter fullscreen mode Exit fullscreen mode

Let’s unpack this carefully.

The Option Type

Option α means:

Either:
- some α
- or none

Enter fullscreen mode Exit fullscreen mode

Like:

  • Rust’s Option<T>
  • Haskell’s Maybe
  • TypeScript’s T | undefined

So:

some x

Enter fullscreen mode Exit fullscreen mode

means:

successful construction

while:

none

Enter fullscreen mode Exit fullscreen mode

means:

validation failed


What Does ⟨s, h⟩ Mean?

This constructs the structure itself.

Equivalent to:

{
  value := s,
  proof := h
}

Enter fullscreen mode Exit fullscreen mode

So:

s, h

Enter fullscreen mode Exit fullscreen mode

creates a valid NonEmptyString.

Then:

some s, h

Enter fullscreen mode Exit fullscreen mode

wraps it into Option.


6. Why This Actually Matters

Now we can write:

def greeting (name : NonEmptyString) : String :=
  s!"Hello {name.value}"

Enter fullscreen mode Exit fullscreen mode

Notice what disappeared:

  • null checks
  • empty checks
  • defensive programming
  • comments explaining assumptions

The invariant is now encoded in the type system.

This is a major shift.

Without refinement types:

function greet(name: string)

Enter fullscreen mode Exit fullscreen mode

every caller must remember the rules.

With refined types:

greeting : NonEmptyString  String

Enter fullscreen mode Exit fullscreen mode

the compiler enforces the rules automatically.


7. The Bigger Idea Behind Type Inhabitation

The deeper point is not “empty strings are bad.”

It is this:

Types can describe semantic reality, not just memory layout.

A few examples:

Type Invariant
NonEmptyString string is non-empty
Fin n integer is < n
AuthenticatedUser login already verified
NonZeroFloat safe divisor
SortedList ordering preserved
VerifiedJWT cryptographically validated

In all these cases:

  • raw input enters the system,
  • validation happens once,
  • stronger types preserve guarantees afterward.

The type system becomes an architecture for trust propagation.

That is far more interesting than “strong typing” in the ordinary sense.


Final Thought

Most codebases are full of invisible assumptions:

  • “this should never be null”
  • “this list should never be empty”
  • “this user should already be authenticated”
  • “this index should be in bounds”

Traditional programming treats these as conventions.

Dependent type systems ask a more radical question:

What if invalid states could not even exist?

And once you start thinking that way, ordinary type systems begin to feel strangely underpowered.

What assumptions in your current codebase could become types instead?


*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.


AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.

See It In Action

See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements

git-lrc-intro-60s.mp4

Why

  • 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production.
  • 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong.
  • 🔁 Build a