Skip to content

Commit cf011ea

Browse files
committed
Expose FunctionK.liftFunction as a part of the Scala 3 API
1 parent dfd9559 commit cf011ea

File tree

4 files changed

+55
-20
lines changed

4 files changed

+55
-20
lines changed

core/src/main/scala-2/cats/arrow/FunctionKMacros.scala

+1-18
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ package arrow
2424

2525
import scala.reflect.macros.blackbox
2626

27-
private[arrow] class FunctionKMacroMethods {
28-
protected type τ[F[_], G[_]]
27+
private[arrow] class FunctionKMacroMethods extends FunctionKLift {
2928

3029
/**
3130
* Lifts function `f` of `F[A] => G[A]` into a `FunctionK[F, G]`.
@@ -48,22 +47,6 @@ private[arrow] class FunctionKMacroMethods {
4847
*/
4948
def lift[F[_], G[_]](f: (F[α] => G[α]) forSome { type α }): FunctionK[F, G] =
5049
macro FunctionKMacros.lift[F, G]
51-
52-
/**
53-
* Lifts function `f` of `F[A] => G[A]` into a `FunctionK[F, G]`.
54-
*
55-
* {{{
56-
* def headOption[A](list: List[A]): Option[A] = list.headOption
57-
* val lifted = FunctionK.liftFunction[List, Option](headOption)
58-
* }}}
59-
*
60-
* Note: The weird `τ[F, G]` parameter is there to compensate for
61-
* the lack of polymorphic function types in Scala 2.
62-
*/
63-
def liftFunction[F[_], G[_]](f: F[τ[F, G]] => G[τ[F, G]]): FunctionK[F, G] =
64-
new FunctionK[F, G] {
65-
def apply[A](fa: F[A]): G[A] = f.asInstanceOf[F[A] => G[A]](fa)
66-
}
6750
}
6851

6952
private[arrow] object FunctionKMacros {

core/src/main/scala-3/cats/arrow/FunctionKMacros.scala

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
package cats
2323
package arrow
2424

25-
private[arrow] class FunctionKMacroMethods {
26-
25+
private[arrow] class FunctionKMacroMethods extends FunctionKLift {
2726
/**
2827
* Lifts function `f` of `[X] => F[X] => G[X]` into a `FunctionK[F, G]`.
2928
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright (c) 2015 Typelevel
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
* this software and associated documentation files (the "Software"), to deal in
6+
* the Software without restriction, including without limitation the rights to
7+
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
* the Software, and to permit persons to whom the Software is furnished to do so,
9+
* subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16+
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18+
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
package cats
23+
package arrow
24+
25+
private[arrow] trait FunctionKLift {
26+
protected type τ[F[_], G[_]]
27+
28+
/**
29+
* Lifts function `f` of `F[A] => G[A]` into a `FunctionK[F, G]`.
30+
*
31+
* {{{
32+
* def headOption[A](list: List[A]): Option[A] = list.headOption
33+
* val lifted = FunctionK.liftFunction[List, Option](headOption)
34+
* }}}
35+
*
36+
* Note: The weird `τ[F, G]` parameter is there to compensate for
37+
* the lack of polymorphic function types in Scala 2.
38+
*
39+
* It is present in Scala 3 API to simplify cross-compilation.
40+
*/
41+
def liftFunction[F[_], G[_]](f: F[τ[F, G]] => G[τ[F, G]]): FunctionK[F, G] =
42+
new FunctionK[F, G] {
43+
def apply[A](fa: F[A]): G[A] = f.asInstanceOf[F[A] => G[A]](fa)
44+
}
45+
}

tests/shared/src/test/scala-3/cats/tests/FunctionKLiftSuite.scala

+8
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,12 @@ class FunctionKLiftSuite extends CatsSuite {
3434
assert(fHeadOption(a) === a.headOption)
3535
}
3636
}
37+
38+
test("lift a function directly using Scala 2 compatible syntax") {
39+
def headOption[A](list: List[A]): Option[A] = list.headOption
40+
val fHeadOption = FunctionK.liftFunction[List, Option](headOption)
41+
forAll { (a: List[Int]) =>
42+
assert(fHeadOption(a) === a.headOption)
43+
}
44+
}
3745
}

0 commit comments

Comments
 (0)