11---
2- title : " \" Five Point Haskell\" Part 2 : Unconditional Election (Parametric Polymorphism)"
2+ title : " \" Five Point Haskell\" : Unconditional Election (Parametric Polymorphism)"
33categories : Haskell
44tags : functional programming, parametric polymorphism
55create-time : 2026/01/01 21:51:17
@@ -18,21 +18,19 @@ ran into in my time.
1818In the last post, we talked about [ Total Depravity] [ ] , which is about treating
1919any mentally-tracked constraint or condition as inevitably leading to a
2020catastrophe and denouncing the reliance on our flawed mental context windows.
21- Embracing the doctrine of total depravity helps us eliminate bugs and potential
22- errors through our types.
2321
2422[ Total Depravity ] : https://blog.jle.im/entry/five-point-haskell-part-1-total-depravity.html
2523
26- However, picking good structures, making invalid states unrepresentable, etc.
27- can only go so far. They are, in the end, tools of human designs and human
28- flaws.
24+ However, stopping here gives us an incomplete picture. Firstly, types aren't
25+ just about preventing bad behaviors. They're about designing good code.
26+ Secondly, there is only so much you can do by picking good structures and
27+ making invalid states unrepresentable. Human tools and human flaws.
2928
30- Types aren't just about preventing bad behaviors. They're about designing good
31- code. And there is one principle that helps guide this design by leveraging the
29+ The next point, to me, is about an aspect of the type system that I see little
30+ coverage of outside of Haskell and typed FP circles, but is a principle of
31+ design that I find permeating everything I write. It's about leveraging the
3232unyielding properties of the universe _ itself_ to take care of our fate, even
33- when we are unable to structure our types well.
34-
35- Let's jump into the second point in five-point Haskell: ** Unconditional
33+ when we are unable to structure our types well. It's ** Unconditional
3634Election** !
3735
3836> Unconditional Election: The power of the ` forall ` to elect or reprobate
@@ -46,58 +44,3 @@ Election**!
4644> things. Embrace one of Haskell's greatest unexpected strengths: the type
4745> parameter.
4846
49- <!-- > Unconditional Election: The _structure_ of your types fully determine the -->
50- <!-- > values and states it will ever take. Nothing at runtime can ever circumvent -->
51- <!-- > this. -->
52- <!-- > -->
53- <!-- > Therefore, take advantage and design the structure of your _types_ to -->
54- <!-- > anticipate the logic you want to model. The program is pre-destined before -->
55- <!-- > you even write any functions. -->
56-
57-
58- <!-- ### Squished Pipeline -->
59-
60- <!-- Along the same lines, there is often the temptation to squish multiple stages -->
61- <!-- along a pipeline into the same type. -->
62-
63- <!-- For example, your "checkout" workflow might incrementally set `Maybe` fields: -->
64-
65- <!-- ```haskell -->
66- <!-- data Checkout = Checkout -->
67- <!-- { items :: [Item] -->
68- <!-- , address :: Maybe Address -->
69- <!-- , payment :: Maybe Token -->
70- <!-- } -->
71- <!-- ``` -->
72-
73- <!-- You start with an empty `Checkout` state...then you add `[Item]`s...then you -->
74- <!-- add `Maybe Address`...then you add `Maybe Token` for payment. However, payment -->
75- <!-- requires an address: -->
76-
77- <!-- ```haskell -->
78- <!-- pay :: Checkout -> IO Checkout -->
79- <!-- pay c = case address c of -->
80- <!-- Just addr -> do -->
81- <!-- tok <- processPayment (items c) addr -->
82- <!-- pure $ c { payment = Just tok } -->
83- <!-- Nothing -> -- uh.... -->
84- <!-- ``` -->
85-
86- <!-- `pay` doesn't _really_ take a `Maybe Address`, it requires an actual `Address`! -->
87- <!-- Its input type is too "big". This is a subtle manifestation of the same -->
88- <!-- problems as shotgun parsing: there is no indication in the type about the -->
89- <!-- actual stage it is in and what operations can legally be done. -->
90-
91- <!-- To fix this, we can just...not keep them all as the same type. -->
92-
93- <!-- ```haskell -->
94- <!-- data PreCheckout = PreCheckout [Item] -->
95- <!-- data PrePayment = PrePayment [Item] Address -->
96- <!-- data PostPayment = PostPayment [Item] Address Token -->
97-
98- <!-- pay :: PrePayment -> IO PostPayment -->
99- <!-- pay (PrePayment items addr) = do -->
100- <!-- tok <- processPayment items addr -->
101- <!-- pure $ PostPayment items addr tok -->
102- <!-- ``` -->
103-
0 commit comments