Skip to content

Commit 8c1ba05

Browse files
committed
refactor: Factor out Utils module.
1 parent 3e80944 commit 8c1ba05

14 files changed

Lines changed: 76 additions & 385 deletions

lambda-calculus-hs.cabal

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ common common-settings
4343
-Wpartial-fields
4444
-Werror=missing-home-modules
4545

46+
library utils
47+
import: common-settings
48+
visibility: private
49+
exposed-modules: Utils
50+
hs-source-dirs: lib
51+
build-depends: base >= 2 && <5, these, semialign
52+
4653
library test-harness
4754
import: common-settings
4855
visibility: private
@@ -108,70 +115,70 @@ executable 00-SimplyTypedEvaluation
108115
import: common-settings
109116
main-is: 00-SimplyTypedEvaluation.hs
110117
hs-source-dirs: main
111-
build-depends: base >= 2 && <5, mtl, transformers, containers
118+
build-depends: base >= 2 && <5, mtl, transformers, containers, utils
112119

113120
executable 01-BidirectionalTypechecking
114121
import: common-settings
115122
main-is: 01-BidirectionalTypechecking.hs
116123
hs-source-dirs: main
117-
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness
124+
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness, utils
118125

119126
executable 02-NormalizationByEvaluation
120127
import: common-settings
121128
main-is: 02-NormalizationByEvaluation.hs
122129
hs-source-dirs: main
123-
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness
130+
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness, utils
124131

125132
executable 03-Elaboration
126133
import: common-settings
127134
main-is: 03-Elaboration.hs
128135
hs-source-dirs: main
129-
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness
136+
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness, utils
130137

131138
executable 04-TypedHoles
132139
import: common-settings
133140
main-is: 04-TypedHoles.hs
134141
hs-source-dirs: main
135-
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness
142+
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness, utils
136143

137144
executable 05-SystemT
138145
import: common-settings
139146
main-is: 05-SystemT.hs
140147
hs-source-dirs: main
141-
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness
148+
build-depends: base >= 2 && <5, mtl, transformers, containers, test-harness, utils
142149

143150
executable 06-Records
144151
import: common-settings
145152
main-is: 06-Records.hs
146153
hs-source-dirs: main
147-
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, test-harness
154+
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, test-harness, utils
148155

149156
executable 07-SumTypes
150157
import: common-settings
151158
main-is: 07-SumTypes.hs
152159
hs-source-dirs: main
153-
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, test-harness
160+
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, test-harness, utils
154161

155162
executable 08-Subtyping
156163
import: common-settings
157164
main-is: 08-Subtyping.hs
158165
hs-source-dirs: main
159-
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness
166+
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness, utils
160167

161168
executable 09-NominalInductiveTypes
162169
import: common-settings
163170
main-is: 09-NominalInductiveTypes.hs
164171
hs-source-dirs: main
165-
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness
172+
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness, utils
166173

167174
executable 09b-IsoInductiveTypes
168175
import: common-settings
169176
main-is: 09b-IsoInductiveTypes.hs
170177
hs-source-dirs: main
171-
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness
178+
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness, utils
172179

173180
executable 10-SystemF
174181
import: common-settings
175182
main-is: 10-SystemF.hs
176183
hs-source-dirs: main
177-
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness
184+
build-depends: base >= 2 && <5, mtl, transformers, containers, these, semialign, scientific, test-harness, utils

lib/Utils.hs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module Utils
2+
( SnocList (..)
3+
, nth
4+
, alignWithM
5+
) where
6+
7+
import Data.Align (Semialign, align)
8+
import Data.These (These)
9+
10+
-- | A list that grows on the right. We use this as our environment
11+
-- representation because it matches the structure of de Bruijn
12+
-- indices: the most recently bound variable is at the end (index 0),
13+
-- and older bindings are further left (higher indices).
14+
--
15+
-- A regular list would work too, but snoc lists make the
16+
-- correspondence between binding order and index explicit.
17+
data SnocList a
18+
= Snoc (SnocList a) a
19+
| Nil
20+
deriving (Show, Eq, Ord, Functor, Foldable)
21+
22+
-- | Look up a value by de Bruijn index, counting from the right
23+
-- (most recent binding).
24+
nth :: SnocList a -> Int -> Maybe a
25+
nth xs i
26+
| i < 0 = Nothing
27+
| otherwise =
28+
let go = \case
29+
(Nil, _) -> Nothing
30+
(Snoc _ x, 0) -> Just x
31+
(Snoc xs' _, i') -> go (xs', i' - 1)
32+
in go (xs, i)
33+
34+
-- | Align two structures and traverse the result. Used by record
35+
-- tactics to check term fields against type fields: 'These' means
36+
-- both present, 'This' means a field in the type but not the term
37+
-- (missing), 'That' means a field in the term but not the type
38+
-- (extra).
39+
alignWithM ::
40+
(Traversable t, Applicative f, Semialign t) =>
41+
(These a b1 -> f b2) ->
42+
t a ->
43+
t b1 ->
44+
f (t b2)
45+
alignWithM f as = traverse f . align as

main/00-SimplyTypedEvaluation.hs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,7 @@ module Main where
1515

1616
import Data.Maybe (fromMaybe)
1717
import Data.String
18-
19-
--------------------------------------------------------------------------------
20-
-- Utils
21-
22-
-- | A list that grows on the right. We use this as our environment
23-
-- representation because it matches the structure of de Bruijn indices: the
24-
-- most recently bound variable is at the end (index 0), and older bindings are
25-
-- further left (higher indices).
26-
--
27-
-- A regular list would work too, but snoc lists make the correspondence between
28-
-- binding order and index explicit.
29-
data SnocList a
30-
= Snoc (SnocList a) a
31-
| Nil
32-
deriving (Show, Eq, Ord, Functor, Foldable)
33-
34-
-- | Look up a value by de Bruijn index, counting from the right (most recent
35-
-- binding).
36-
nth :: SnocList a -> Int -> Maybe a
37-
nth xs i
38-
| i < 0 = Nothing
39-
| otherwise =
40-
let go = \case
41-
(Nil, _) -> Nothing
42-
(Snoc _ x, 0) -> Just x
43-
(Snoc xs' _, i') -> go (xs', i' - 1)
44-
in go (xs, i)
18+
import Utils (SnocList (..), nth)
4519

4620
--------------------------------------------------------------------------------
4721
-- Syntax

main/01-BidirectionalTypechecking.hs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,7 @@ import Data.String
2323
import PrettyTerm (Prec, appPrec, arrowPrec, arrowSym, atomPrec, lamPrec, lambdaSym, parensIf)
2424
import PrettyTerm qualified as PP
2525
import TestHarness (RunResult (..), runTest, runTestErr, section)
26-
27-
--------------------------------------------------------------------------------
28-
-- Utils
29-
30-
-- | A list that grows on the right. We use this as our environment
31-
-- representation because it matches the structure of de Bruijn indices: the
32-
-- most recently bound variable is at the end (index 0), and older bindings are
33-
-- further left (higher indices).
34-
--
35-
-- A regular list would work too, but snoc lists make the correspondence between
36-
-- binding order and index explicit.
37-
data SnocList a
38-
= Snoc (SnocList a) a
39-
| Nil
40-
deriving (Show, Eq, Ord, Functor, Foldable)
41-
42-
-- | Look up a value by de Bruijn index, counting from the right (most recent
43-
-- binding).
44-
nth :: SnocList a -> Int -> Maybe a
45-
nth xs i
46-
| i < 0 = Nothing
47-
| otherwise =
48-
let go = \case
49-
(Nil, _) -> Nothing
50-
(Snoc _ x, 0) -> Just x
51-
(Snoc xs' _, i') -> go (xs', i' - 1)
52-
in go (xs, i)
26+
import Utils (SnocList (..), nth)
5327

5428
--------------------------------------------------------------------------------
5529
-- Syntax

main/02-NormalizationByEvaluation.hs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,7 @@ import Data.String
2626
import PrettyTerm (Prec, appPrec, arrowPrec, arrowSym, atomPrec, lamPrec, lambdaSym, parensIf)
2727
import PrettyTerm qualified as PP
2828
import TestHarness (RunResult (..), runTest, runTestErr, section)
29-
30-
--------------------------------------------------------------------------------
31-
-- Utils
32-
33-
-- | A list that grows on the right. We use this as our environment
34-
-- representation because it matches the structure of de Bruijn indices: the
35-
-- most recently bound variable is at the end (index 0), and older bindings are
36-
-- further left (higher indices).
37-
--
38-
-- A regular list would work too, but snoc lists make the correspondence between
39-
-- binding order and index explicit.
40-
data SnocList a
41-
= Snoc (SnocList a) a
42-
| Nil
43-
deriving (Show, Eq, Ord, Functor, Foldable)
44-
45-
-- | Look up a value by de Bruijn index, counting from the right (most recent
46-
-- binding).
47-
nth :: SnocList a -> Int -> Maybe a
48-
nth xs i
49-
| i < 0 = Nothing
50-
| otherwise =
51-
let go = \case
52-
(Nil, _) -> Nothing
53-
(Snoc _ x, 0) -> Just x
54-
(Snoc xs' _, i') -> go (xs', i' - 1)
55-
in go (xs, i)
29+
import Utils (SnocList (..), nth)
5630

5731
--------------------------------------------------------------------------------
5832
-- Syntax

main/03-Elaboration.hs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,7 @@ import Data.String
2727
import PrettyTerm (Prec, appPrec, arrowPrec, arrowSym, atomPrec, lamPrec, lambdaSym, parensIf)
2828
import PrettyTerm qualified as PP
2929
import TestHarness (RunResult (..), runTest, runTestErr, section)
30-
31-
--------------------------------------------------------------------------------
32-
-- Utils
33-
34-
-- | A list that grows on the right. We use this as our environment
35-
-- representation because it matches the structure of de Bruijn indices: the
36-
-- most recently bound variable is at the end (index 0), and older bindings are
37-
-- further left (higher indices).
38-
--
39-
-- A regular list would work too, but snoc lists make the correspondence between
40-
-- binding order and index explicit.
41-
data SnocList a
42-
= Snoc (SnocList a) a
43-
| Nil
44-
deriving (Show, Eq, Ord, Functor, Foldable)
45-
46-
-- | Look up a value by de Bruijn index, counting from the right (most recent
47-
-- binding).
48-
nth :: SnocList a -> Int -> Maybe a
49-
nth xs i
50-
| i < 0 = Nothing
51-
| otherwise =
52-
let go = \case
53-
(Nil, _) -> Nothing
54-
(Snoc _ x, 0) -> Just x
55-
(Snoc xs' _, i') -> go (xs', i' - 1)
56-
in go (xs, i)
30+
import Utils (SnocList (..), nth)
5731

5832
--------------------------------------------------------------------------------
5933
-- Syntax

main/04-TypedHoles.hs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,7 @@ import Data.String
2727
import PrettyTerm (Prec, appPrec, arrowPrec, arrowSym, atomPrec, lamPrec, lambdaSym, parensIf)
2828
import PrettyTerm qualified as PP
2929
import TestHarness (RunResult (..), runTest, runTestErr, section)
30-
31-
--------------------------------------------------------------------------------
32-
-- Utils
33-
34-
-- | A list that grows on the right. We use this as our environment
35-
-- representation because it matches the structure of de Bruijn indices: the
36-
-- most recently bound variable is at the end (index 0), and older bindings are
37-
-- further left (higher indices).
38-
--
39-
-- A regular list would work too, but snoc lists make the correspondence between
40-
-- binding order and index explicit.
41-
data SnocList a
42-
= Snoc (SnocList a) a
43-
| Nil
44-
deriving (Show, Eq, Ord, Functor, Foldable)
45-
46-
-- | Look up a value by de Bruijn index, counting from the right (most recent
47-
-- binding).
48-
nth :: SnocList a -> Int -> Maybe a
49-
nth xs i
50-
| i < 0 = Nothing
51-
| otherwise =
52-
let go = \case
53-
(Nil, _) -> Nothing
54-
(Snoc _ x, 0) -> Just x
55-
(Snoc xs' _, i') -> go (xs', i' - 1)
56-
in go (xs, i)
30+
import Utils (SnocList (..), nth)
5731

5832
--------------------------------------------------------------------------------
5933
-- Syntax

main/05-SystemT.hs

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,33 +27,7 @@ import Data.String
2727
import PrettyTerm (Prec, appPrec, arrowPrec, arrowSym, atomPrec, lamPrec, lambdaSym, parensIf)
2828
import PrettyTerm qualified as PP
2929
import TestHarness (RunResult (..), runTest, runTestErr, section)
30-
31-
--------------------------------------------------------------------------------
32-
-- Utils
33-
34-
-- | A list that grows on the right. We use this as our environment
35-
-- representation because it matches the structure of de Bruijn indices: the
36-
-- most recently bound variable is at the end (index 0), and older bindings are
37-
-- further left (higher indices).
38-
--
39-
-- A regular list would work too, but snoc lists make the correspondence between
40-
-- binding order and index explicit.
41-
data SnocList a
42-
= Snoc (SnocList a) a
43-
| Nil
44-
deriving (Show, Eq, Ord, Functor, Foldable)
45-
46-
-- | Look up a value by de Bruijn index, counting from the right (most recent
47-
-- binding).
48-
nth :: SnocList a -> Int -> Maybe a
49-
nth xs i
50-
| i < 0 = Nothing
51-
| otherwise =
52-
let go = \case
53-
(Nil, _) -> Nothing
54-
(Snoc _ x, 0) -> Just x
55-
(Snoc xs' _, i') -> go (xs', i' - 1)
56-
in go (xs, i)
30+
import Utils (SnocList (..), nth)
5731

5832
--------------------------------------------------------------------------------
5933
-- Syntax

0 commit comments

Comments
 (0)