2026-04-22 15:43:26 +02:00
|
|
|
# Haskell Newtypes and Smart Constructors
|
|
|
|
|
|
|
|
|
|
This note covers `09-haskell-newtype/`, which models validated user input with `newtype`, record fields, and smart constructors.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 1. Why `newtype` Matters
|
|
|
|
|
|
2026-04-22 15:44:05 +02:00
|
|
|
Plain `Text` values do not tell you what they represent. A user name and an email address could both be `Text`, even though they mean different
|
|
|
|
|
things.
|
2026-04-22 15:43:26 +02:00
|
|
|
|
|
|
|
|
This example wraps those concepts explicitly:
|
|
|
|
|
|
|
|
|
|
- `UserName`,
|
|
|
|
|
- `Email`, and
|
|
|
|
|
- `Registration`.
|
|
|
|
|
|
|
|
|
|
That lets the rest of the code depend on validated domain types instead of raw input.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 2. Smart Constructors
|
|
|
|
|
|
|
|
|
|
The module exposes constructor functions like `mkUserName` and `mkEmail`, which return `Either String ...`.
|
|
|
|
|
|
|
|
|
|
That is the main idea:
|
|
|
|
|
|
|
|
|
|
- invalid input is rejected at the boundary,
|
|
|
|
|
- successful validation returns a domain type, and
|
|
|
|
|
- the rest of the program works with trusted values.
|
|
|
|
|
|
|
|
|
|
This is a common intermediate Haskell pattern because it pushes validation close to the edge of the program.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 3. Commands to Try
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd 09-haskell-newtype
|
|
|
|
|
|
|
|
|
|
nix develop
|
|
|
|
|
cabal run
|
|
|
|
|
cabal run -- learner learner@example.com
|
|
|
|
|
cabal test
|
|
|
|
|
|
|
|
|
|
nix build
|
|
|
|
|
./result/bin/mini-registration learner learner@example.com
|
|
|
|
|
|
|
|
|
|
nix run . -- learner learner@example.com
|
|
|
|
|
nix flake check
|
|
|
|
|
```
|