Skip to content

Commit aab1672

Browse files
committed
renaming
1 parent 708e6b8 commit aab1672

File tree

7 files changed

+18
-18
lines changed

7 files changed

+18
-18
lines changed
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
2-
title: "Extreme Haskell: Typed Lambda Calculus"
2+
title: "Extreme Haskell: Typed State Machines with Typed Lambda Calculus"
33
categories: Haskell
44
tags: functional programming, dependent types, haskell, singletons, types
55
create-time: 2026/02/07 12:30:55
6-
identifier: typed-lc-1
7-
slug: extreme-haskell-typed-lambda-calculus
6+
identifier: typed-sm-lc
7+
slug: extreme-haskell-typed-state-machines-with-typed-lambda-calculus
88
---
99

1010
I always say, inside every Haskeller there are two wolves, living on both ends
@@ -59,10 +59,10 @@ monstrosity we are about to explore in this post?
5959
All of the code here is [available online][code samples], and if you check out
6060
the repo and run `nix develop` you should be able to load it all in ghci:
6161

62-
!!![code samples]:typed-lc/flake.nix
62+
!!![code samples]:typed-sm-lc/flake.nix
6363

6464
```bash
65-
$ cd code-samples/typed-lc
65+
$ cd code-samples/typed-sm-lc
6666
$ nix develop
6767
$ ghci
6868
ghci> :load Stage1.hs
@@ -79,14 +79,14 @@ in.
7979
One basic thing we can do is start with:
8080

8181
```haskell
82-
!!!typed-lc/Stage1.hs "data Prim" "data Op" "data Expr"
82+
!!!typed-sm-lc/Stage1.hs "data Prim" "data Op" "data Expr"
8383
```
8484

8585
And you can write `(\x -> x * 3) 5` as:
8686

8787

8888
```haskell
89-
!!!typed-lc/Stage1.hs "fifteen ::"
89+
!!!typed-sm-lc/Stage1.hs "fifteen ::"
9090
```
9191

9292
You can definitely easily render this in a graph, but what happens when you
@@ -95,7 +95,7 @@ What would the type even be? `eval :: Expr -> Maybe Prim`? Maybe just
9595
`normalize :: Expr -> Expr` and hope that the result is `Prim`?
9696

9797
```haskell
98-
!!!typed-lc/Stage1.hs "normalize ::"
98+
!!!typed-sm-lc/Stage1.hs "normalize ::"
9999
```
100100

101101
This would properly evaluate:
@@ -112,7 +112,7 @@ But this isn't type-safe...we have undefined branches still. We could make the
112112
entire thing monadic by returning `Maybe`:
113113

114114
```haskell
115-
!!!typed-lc/Stage2.hs "normalize ::"
115+
!!!typed-sm-lc/Stage2.hs "normalize ::"
116116
```
117117

118118
This kind of works if you remember to thread everything through `Maybe` (or
@@ -137,7 +137,7 @@ The next step you'll see in posts online is to add a phantom index type to
137137
`Expr`:
138138

139139
```haskell
140-
!!!typed-lc/Stage3.hs "type data Ty" "data STy" "data Prim" "data Op" "data Expr"
140+
!!!typed-sm-lc/Stage3.hs "type data Ty" "data STy" "data Prim" "data Op" "data Expr"
141141
```
142142

143143
Here we use `-XTypeData` to define a data kind, `Ty` is a kind with types
@@ -148,7 +148,7 @@ domain's `Bool`, or our domain's `String`. At least, now, it is impossible to
148148
create an `Expr` that doesn't type check:
149149

150150
```haskell
151-
!!!typed-lc/Stage3.hs "fifteen ::"
151+
!!!typed-sm-lc/Stage3.hs "fifteen ::"
152152
```
153153

154154
We also need a [singleton][] for our `Ty` type, `STy`...this makes a whole lot
@@ -167,7 +167,7 @@ we still have issues here.
167167
But now at least we can write `eval`:
168168

169169
```haskell
170-
!!!typed-lc/Stage3.hs "data EValue" "data SomeValue" "sameTy ::" "eval ::"
170+
!!!typed-sm-lc/Stage3.hs "data EValue" "data SomeValue" "sameTy ::" "eval ::"
171171
```
172172

173173
What did we gain here? We have a type-safe `eval` now that will create a
@@ -189,7 +189,7 @@ environment.
189189
We'll have:
190190

191191
```haskell
192-
!!!typed-lc/Stage4.hs "data Expr ::"1 "type (:::)"
192+
!!!typed-sm-lc/Stage4.hs "data Expr ::"1 "type (:::)"
193193
```
194194

195195
So a value of type `Expr '["x" ::: TInt, "y" ::: TBool]` is an expression with
@@ -200,14 +200,14 @@ an `Expr` of a function type: (and `KnownSymbol` instance so that we can debug
200200
print the variable name)
201201

202202
```haskell
203-
!!!typed-lc/Stage4.hs "ELambda ::"
203+
!!!typed-sm-lc/Stage4.hs "ELambda ::"
204204
```
205205

206206
So how do we implement `Var`? We have to gate it on whether or not the free
207207
variable is available in the environment. For that, we can use `Index`:
208208

209209
```haskell
210-
!!!typed-lc/Stage4.hs "data Index ::"
210+
!!!typed-sm-lc/Stage4.hs "data Index ::"
211211
```
212212

213213
I have this in [functor-products][], but it's also `CoRec Proxy` from [vinyl][]
@@ -225,15 +225,15 @@ b`, and `IS (IS IZ) :: Index '[a,b,c] c`. So, if we require `Var` to take an
225225
variable list and at that given index:
226226

227227
```haskell
228-
!!!typed-lc/Stage4.hs "EVar ::"
228+
!!!typed-sm-lc/Stage4.hs "EVar ::"
229229
```
230230

231231
So it is legal to have `EVar IZ :: Expr '["x" ::: TInt, "y" ::: TBool] TInt`, and
232232
also it is automatically inferred to be a `TInt`. But we could _not_ write
233233
`EVar IZ :: Expr '[] TInt`.
234234

235235
```haskell
236-
!!!typed-lc/Stage4.hs "data Expr ::" "eLambda ::" "fifteen ::"
236+
!!!typed-sm-lc/Stage4.hs "data Expr ::" "eLambda ::" "fifteen ::"
237237
```
238238

239239
In GHC 9.12 we can write `eLambda` using `RequiredTypeArguments` and so can
@@ -252,5 +252,5 @@ these variables, and for this we can use `Rec` (from [vinyl][]) or `NP` from
252252
[sop-core]:
253253

254254
```haskell
255-
!!!typed-lc/Stage4.hs "data Rec" "indexRec ::" "eval ::"
255+
!!!typed-sm-lc/Stage4.hs "data Rec" "indexRec ::" "eval ::"
256256
```

0 commit comments

Comments
 (0)