@@ -31,8 +31,8 @@ import Data.Either (Either(..))
3131
3232newtype Percent = Percent Number
3333data Point = Point Number Number
34-
35- data Fill
34+
35+ data Fill -- think of a paint program filling a shape
3636 = Solid Color
3737 | LinearGradient Color Color Percent
3838 | RadialGradient Color Color Point
@@ -50,7 +50,7 @@ fillRadial :: Fill
5050fillRadial = RadialGradient Color .white Color .black $ Point 1.0 3.4
5151
5252
53- {- ----- Eq and Show come in handy ------}
53+ {- ----- Eq and Show come in handy ------}
5454
5555derive instance genericPercent :: Generic Percent _
5656instance eqPercent :: Eq Percent where
@@ -72,11 +72,10 @@ instance showFill :: Show Fill where
7272
7373
7474 {- ----- Making prisms with Maybe and `prism'` ------}
75- {- ----- Basic usage: `preview`, `review`, `is`, and `isn't` ------}
7675
77- -- Two function arguments: a data constructor for the type in
78- -- question, plus one that converts your desired case to a
79- -- `Just <wrapped values>` or `Nothing`.
76+ -- `prism'` (note the apostrophe) takes two functions. One is a data
77+ -- constructor for the type in question. The other converts your
78+ -- desired case to a `Just <wrapped values>` or `Nothing`.
8079
8180solidFocus :: Prism' Fill Color
8281solidFocus = prism' constructor focus
@@ -89,19 +88,24 @@ solidFocus = prism' constructor focus
8988-- In real life, you might abbreviate the above to this:
9089
9190solidFocus' :: Prism' Fill Color
92- solidFocus' = prism' Solid case _ of
91+ solidFocus' = prism' Solid case _ of
9392 Solid color -> Just color
9493 _ -> Nothing
9594
9695-- ... but being painfully explicit is better for examples.
9796
97+
98+ {- ----- Basic usage: `preview`, `review`, `is`, and `isn't` ------}
99+
98100-- After building a prism, you focus in on a color with `preview`:
99101
100102s1 :: Maybe Color
101- s1 = preview solidFocus (Solid Color .white) -- (Just rgba 255 255 255 1.0)
103+ s1 = preview solidFocus (Solid Color .white)
104+ -- (Just rgba 255 255 255 1.0)
102105
103106s2 :: Maybe Color
104- s2 = preview solidFocus fillRadial -- Nothing
107+ s2 = preview solidFocus fillRadial
108+ -- Nothing
105109
106110-- ... or you can create a Fill from a color with `review`:
107111
@@ -112,28 +116,32 @@ s3 = review solidFocus Color.white
112116-- ... or you can ask whether a given value matches the prism:
113117
114118s4 :: Boolean
115- s4 = is solidFocus (Solid Color .white) :: Boolean -- true
119+ s4 = is solidFocus (Solid Color .white) :: Boolean
120+ -- true
116121
117122s5 :: Boolean
118- s5 = isn't solidFocus (Solid Color .white) :: Boolean -- false
119-
123+ s5 = isn't solidFocus (Solid Color .white) :: Boolean
124+ -- false
120125
121126
122127 {- ----- Making prisms with Either and `prism` ------}
123128
124- -- Since `LinearGradient` wraps multiple values , they need to be
125- -- rewrapped for `preview`. I'll use a record.
126-
129+ -- Since `LinearGradient` wraps two colors and a percent , they need to
130+ -- be bundled together into a single value for `preview` to
131+ -- return. I'll use a record:
127132
128133type LinearInterchange =
129134 { color1 :: Color
130135 , color2 :: Color
131136 , percent :: Percent
132137 }
133138
134- -- When making a prism with `prism`, the "focus" function returns
135- -- either the selected value (as `Right`) or the entire argument (as
136- -- `Left`).
139+ -- (In real life, you probably wouldn't have to give such a record a
140+ -- type alias.)
141+
142+ -- When making a prism with `prism` (no apostrophe), the "focus"
143+ -- function returns either the selected value (as a `Right`) or the
144+ -- entire argument (as a `Left`).
137145
138146linearFocus :: Prism' Fill LinearInterchange
139147linearFocus = prism constructor focus
@@ -142,11 +150,11 @@ linearFocus = prism constructor focus
142150 LinearGradient color1 color2 percent
143151 focus = case _ of
144152 LinearGradient color1 color2 percent ->
145- Right {color1, color2, percent}
146- fill ->
147- Left fill
148-
149- -- Even though made differently, this prism is used the same way:
153+ Right {color1, color2, percent}
154+ otherFill ->
155+ Left otherFill
156+
157+ -- Even though made differently, this `linearFocus` is used the same way:
150158
151159l1 :: String
152160l1 = preview linearFocus fillBlackToWhite # maybe " !" showRecord
@@ -158,6 +166,7 @@ l2 = review linearFocus { color1 : Color.black
158166 , percent : Percent 33.3
159167 }
160168
169+
161170 {- ----- Constructing more specific prisms ------}
162171
163172-- `only` is used to check for a specific value:
@@ -166,54 +175,61 @@ whiteToBlackFocus :: Prism' Fill Unit
166175whiteToBlackFocus = only fillWhiteToBlack
167176
168177o1 :: Boolean
169- o1 = is whiteToBlackFocus fillWhiteToBlack :: Boolean -- true
178+ o1 = is whiteToBlackFocus fillWhiteToBlack :: Boolean
179+ -- true
170180
171181o2 :: Boolean
172- o2 = is whiteToBlackFocus fillBlackToWhite :: Boolean -- false
182+ o2 = is whiteToBlackFocus fillBlackToWhite :: Boolean
183+ -- false
173184
174185o3 :: Boolean
175- o3 = is whiteToBlackFocus fillRadial :: Boolean -- false
176-
186+ o3 = is whiteToBlackFocus fillRadial :: Boolean
187+ -- false
177188
178189-- `nearly` is typically used to look for a specific case (like other
179- -- prisms), but accepting only values that are close to some target
180- -- value. It takes two values: a reference value (which, with sum types,
181- -- serves to declare the focus case, and a predicate that determines
182- -- whether the wrapped value(s) is close enough to what's desired.
190+ -- prisms), but also accepts only values that are close to some target
191+ -- value. It takes two values: a reference value, and a predicate that
192+ -- determines whether the wrapped value(s) are close enough to the
193+ -- reference. Note that the predicate takes the "whole" type (here,
194+ -- `Fill`), not the unwrapped values inside the case you care about.
183195
184196-- In this example, we want to focus on solid colors that are "bright
185- -- enough".
197+ -- enough."
186198
187199brightSolidFocus :: Prism' Fill Unit
188200brightSolidFocus = nearly (Solid referenceColor) predicate
189201 where
190202 referenceColor = Color .graytone 0.8
191203 predicate = case _ of
192- Solid color ->
204+ Solid color ->
193205 Color .brightness color >= Color .brightness referenceColor
194206 _ ->
195207 false
196208
197- -- Because a `nearly` prism focuses on `Unit`, you get only two values
198- -- from `preview`:
199-
209+ -- Because a `nearly` prism focuses into `Unit`, you can get only two
210+ -- values from `preview`:
200211
201212n1 :: Maybe Unit
202- n1 = preview brightSolidFocus (Solid Color .white) -- (Just unit)
213+ n1 = preview brightSolidFocus (Solid Color .white)
214+ -- (Just unit)
203215
204216n2 :: Maybe Unit
205- n2 = preview brightSolidFocus (Solid Color .black) -- Nothing
217+ n2 = preview brightSolidFocus (Solid Color .black)
218+ -- Nothing
206219
207220n3 :: Maybe Unit
208- n3 = preview brightSolidFocus NoFill -- Nothing
221+ n3 = preview brightSolidFocus NoFill
222+ -- Nothing
223+
209224
210-
211- -- So you probably want to use `is` or `isn't`:
225+ -- ... so you probably want to use `is` or `isn't`:
212226
213227n4 :: Boolean
214- n4 = is brightSolidFocus (Solid Color .white) :: Boolean -- true
228+ n4 = is brightSolidFocus (Solid Color .white) :: Boolean
229+ -- true
215230
216231-- You can recover the reference value with `review`:
217232
218233n5 :: Fill
219- n5 = review brightSolidFocus unit -- (Solid rgba 204 204 204 1.0)
234+ n5 = review brightSolidFocus unit
235+ -- (Solid rgba 204 204 204 1.0)
0 commit comments