@@ -17,6 +17,21 @@ sealed abstract class Free[S[_], A] extends Product with Serializable {
17
17
final def map [B ](f : A => B ): Free [S , B ] =
18
18
flatMap(a => Pure (f(a)))
19
19
20
+ /**
21
+ * Modify the functor context `S` using transformation `f`.
22
+ *
23
+ * This is effectively compiling your free monad into another
24
+ * language by changing the suspension functor using the given
25
+ * natural transformation `f`.
26
+ *
27
+ * If your natural transformation is effectful, be careful. These
28
+ * effects will be applied by `mapK`.
29
+ */
30
+ final def mapK [T [_]](f : S ~> T ): Free [T , A ] =
31
+ foldMap[Free [T , ? ]] { // this is safe because Free is stack safe
32
+ λ[FunctionK [S , Free [T , ? ]]](fa => Suspend (f(fa)))
33
+ }(Free .catsFreeMonadForFree)
34
+
20
35
/**
21
36
* Bind the given continuation to the result of this computation.
22
37
* All left-associated binds are reassociated to the right.
@@ -147,11 +162,8 @@ sealed abstract class Free[S[_], A] extends Product with Serializable {
147
162
*
148
163
* If your natural transformation is effectful, be careful. These
149
164
* effects will be applied by `compile`.
150
- */
151
- final def compile [T [_]](f : FunctionK [S , T ]): Free [T , A ] =
152
- foldMap[Free [T , ? ]] { // this is safe because Free is stack safe
153
- λ[FunctionK [S , Free [T , ? ]]](fa => Suspend (f(fa)))
154
- }(Free .catsFreeMonadForFree)
165
+ */
166
+ final def compile [T [_]](f : FunctionK [S , T ]): Free [T , A ] = mapK(f)
155
167
156
168
/**
157
169
* Lift into `G` (typically a `EitherK`) given `InjectK`. Analogous
@@ -169,7 +181,7 @@ sealed abstract class Free[S[_], A] extends Product with Serializable {
169
181
*}}}
170
182
*/
171
183
final def inject [G [_]](implicit ev : InjectK [S , G ]): Free [G , A ] =
172
- compile (λ[S ~> G ](ev.inj(_)))
184
+ mapK (λ[S ~> G ](ev.inj(_)))
173
185
174
186
override def toString : String =
175
187
" Free(...)"
@@ -217,11 +229,17 @@ object Free extends FreeInstances {
217
229
def defer [F [_], A ](value : => Free [F , A ]): Free [F , A ] =
218
230
pure(()).flatMap(_ => value)
219
231
232
+ /**
233
+ * a FunctionK, suitable for composition, which calls mapK
234
+ */
235
+ def mapK [F [_], G [_]](fk : FunctionK [F , G ]): FunctionK [Free [F , ? ], Free [G , ? ]] =
236
+ λ[FunctionK [Free [F , ? ], Free [G , ? ]]](f => f.mapK(fk))
237
+
220
238
/**
221
239
* a FunctionK, suitable for composition, which calls compile
222
240
*/
223
241
def compile [F [_], G [_]](fk : FunctionK [F , G ]): FunctionK [Free [F , ? ], Free [G , ? ]] =
224
- λ[ FunctionK [ Free [ F , ? ], Free [ G , ? ]]](f => f.compile(fk) )
242
+ mapK(fk )
225
243
226
244
/**
227
245
* a FunctionK, suitable for composition, which calls foldMap
0 commit comments