Skip to content

Commit 406d125

Browse files
committed
Merge pull request #244 from puffnfresh/feature/option-optics
Add some optics for Option
2 parents 521de97 + 5f1d7ad commit 406d125

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

core/src/main/java/fj/data/Option.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import fj.Equal;
2020
import fj.Ord;
2121
import fj.Hash;
22+
import fj.data.optic.Prism;
23+
import fj.data.optic.PPrism;
2224
import static fj.Function.*;
2325
import static fj.P.p;
2426
import static fj.Unit.unit;
@@ -30,6 +32,8 @@
3032
import static fj.data.Validation.parseInt;
3133
import static fj.data.Validation.parseLong;
3234
import static fj.data.Validation.parseShort;
35+
import static fj.data.optic.Prism.prism;
36+
import static fj.data.optic.PPrism.pPrism;
3337
import static fj.Show.optionShow;
3438

3539
import java.util.Collection;
@@ -883,4 +887,34 @@ public static <A> F<Option<Option<A>>, Option<A>> join() {
883887
* A function that parses a string to a short.
884888
*/
885889
public static final F<String, Option<Short>> parseShort = s -> parseShort(s).toOption();
890+
891+
public static final class Optic {
892+
893+
private Optic() {
894+
throw new UnsupportedOperationException();
895+
}
896+
897+
/**
898+
* None prism
899+
*/
900+
public static <A> Prism<Option<A>, Unit> none() {
901+
return prism(o -> o.option(Option.some(Unit.unit()), a -> Option.none()), u -> Option.none());
902+
}
903+
904+
/**
905+
* Polymorphic Some prism
906+
*/
907+
public static <A, B> PPrism<Option<A>, Option<B>, A, B> pSome() {
908+
return pPrism(o -> o.<Either<Option<B>, A>>map(Either::right).orSome(Either.left(Option.none())), Option::some);
909+
}
910+
911+
/**
912+
* Monomorphic Some prism
913+
*/
914+
public static <A> Prism<Option<A>, A> some() {
915+
return new Prism<>(pSome());
916+
}
917+
918+
}
919+
886920
}

props-core-scalacheck/src/main/scala/fj/package.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import fj.Equal
2-
import fj.data.List
2+
import fj.data.{Option, List}
33
package object fj {
44
implicit def Function1F[A, B](g: A => B): F[A, B] = new F[A, B] {
55
def f(a: A) = g(a)
@@ -16,9 +16,11 @@ package object fj {
1616
implicit def intEqual: Equal[Int] = Equal.equal({(i1:Int, i2:Int) => Boolean.box((i1 == i2))})
1717

1818
implicit def unitEqual: Equal[Unit] = Equal.anyEqual()
19-
19+
2020
implicit def listEqual[A](implicit aEq: Equal[A]): Equal[List[A]] = Equal.listEqual(aEq)
21-
21+
22+
implicit def optionEqual[A](implicit aEq: Equal[A]): Equal[Option[A]] = Equal.optionEqual(aEq)
23+
2224
implicit def p2Equal[A, B](implicit aEq: Equal[A], bEq: Equal[B]): Equal[P2[A, B]] = Equal.p2Equal(aEq, bEq)
2325

2426
}

props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package fj
22
package data
33

4+
import fj.data.optic.PrismLaws
45
import org.scalacheck.Prop._
56
import ArbitraryOption.arbitraryOption
67
import ArbitraryP.arbitraryP1
8+
import ArbitraryUnit._
79
import Equal.{optionEqual, stringEqual}
810
import Unit.unit
911
import Option.{none, some, join}
@@ -84,4 +86,10 @@ object CheckOption extends Properties("Option") {
8486
a.isNone || optionEqual(stringEqual).eq(
8587
join(a),
8688
a.some))
89+
90+
property("Optic.pSome") = PrismLaws[Option[String], String](Option.Optic.pSome())
91+
92+
property("Optic.some") = PrismLaws[Option[String], String](Option.Optic.some())
93+
94+
property("Optic.none") = PrismLaws[Option[Unit], Unit](Option.Optic.none())
8795
}

0 commit comments

Comments
 (0)