├── .gitattributes
├── .gitignore
├── .travis.yml
├── README.md
├── base
├── build.gradle
└── src
│ ├── main
│ └── groovy
│ │ └── com
│ │ └── github
│ │ └── mperry
│ │ └── fg
│ │ └── YCombinator.groovy
│ └── test
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ └── YCombinatorTest.groovy
├── build.gradle
├── consume
├── build.gradle
├── scripts
│ ├── bugImplicitBoxing.groovy
│ ├── exceptionHandling.groovy
│ ├── genericTypeCheck.groovy
│ ├── listMonadTest.groovy
│ ├── optionMonadTest.groovy
│ ├── setMonadTest.groovy
│ └── test.groovy
└── src
│ └── test
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ ├── Example.groovy
│ └── FutureTest.groovy
├── core
├── build.gradle
└── src
│ ├── main
│ ├── groovy
│ │ └── com
│ │ │ └── github
│ │ │ └── mperry
│ │ │ └── fg
│ │ │ ├── ClassExtension.groovy
│ │ │ ├── CollectionExtension.groovy
│ │ │ ├── EitherExtension.groovy
│ │ │ ├── F2Extension.groovy
│ │ │ ├── F2StaticExtension.groovy
│ │ │ ├── F3Extension.groovy
│ │ │ ├── F3StaticExtension.groovy
│ │ │ ├── F4Extension.groovy
│ │ │ ├── F4StaticExtension.groovy
│ │ │ ├── F5Extension.groovy
│ │ │ ├── F5StaticExtension.groovy
│ │ │ ├── F6Extension.groovy
│ │ │ ├── F6StaticExtension.groovy
│ │ │ ├── F7Extension.groovy
│ │ │ ├── F7StaticExtension.groovy
│ │ │ ├── F8Extension.groovy
│ │ │ ├── F8StaticExtension.groovy
│ │ │ ├── FExtension.groovy
│ │ │ ├── FStaticExtension.groovy
│ │ │ ├── IntegerExtension.groovy
│ │ │ ├── ListFJExtension.groovy
│ │ │ ├── ListJavaExtension.groovy
│ │ │ ├── ListJavaStaticExtension.groovy
│ │ │ ├── ListOps.groovy
│ │ │ ├── ObjectCompanion.groovy
│ │ │ ├── ObjectExtension.groovy
│ │ │ ├── OptionExtension.groovy
│ │ │ ├── OptionStaticExtension.groovy
│ │ │ ├── P1Extension.groovy
│ │ │ ├── Rand.groovy
│ │ │ ├── ShowExtension.groovy
│ │ │ ├── ShowStaticExtension.groovy
│ │ │ ├── ShowWorkaroundGroovy.groovy
│ │ │ ├── StreamExtension.groovy
│ │ │ └── test
│ │ │ ├── ArbitraryCompanion.groovy
│ │ │ ├── ArbitraryExtension.groovy
│ │ │ ├── ArbitraryStaticExtension.groovy
│ │ │ ├── ArgExtension.groovy
│ │ │ ├── ArgStaticExtension.groovy
│ │ │ ├── CheckResultCompanion.groovy
│ │ │ ├── CheckResultExtension.groovy
│ │ │ ├── CheckResultStaticExtension.groovy
│ │ │ ├── CoarbitraryCompanion.groovy
│ │ │ ├── GenExtension.groovy
│ │ │ ├── GenStaticExtension.groovy
│ │ │ └── PropertyExtension.groovy
│ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── mperry
│ │ │ └── ShowWorkaroundJava.java
│ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── org.codehaus.groovy.runtime.ExtensionModule
│ └── test
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ └── RandTest.groovy
├── demo
├── build.gradle
└── src
│ ├── main
│ └── groovy
│ │ └── com
│ │ └── github
│ │ └── mperry
│ │ └── fg
│ │ ├── ExceptionHandling.groovy
│ │ ├── FileList.groovy
│ │ ├── Keno.groovy
│ │ ├── MyTest.groovy
│ │ ├── PaperScissorsRock.groovy
│ │ ├── SimpleIODemoFunctional.groovy
│ │ ├── SimpleIODemoImperative.groovy
│ │ ├── StateGame.groovy
│ │ ├── Test1.groovy
│ │ ├── di
│ │ ├── App.groovy
│ │ ├── Config.groovy
│ │ ├── ConfigReader.groovy
│ │ ├── User.groovy
│ │ └── UserRepository.groovy
│ │ ├── state
│ │ ├── Input.groovy
│ │ ├── Machine.groovy
│ │ └── MachineSimulation.groovy
│ │ └── trampoline
│ │ └── TrampolineClosureTest.groovy
│ └── test
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ ├── KenoTest.groovy
│ ├── TrampolineTest.groovy
│ └── state
│ └── MachineTest.groovy
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── java8
├── build.gradle
└── src
│ └── main
│ ├── groovy
│ └── com
│ │ └── github
│ │ └── mperry
│ │ └── fg
│ │ ├── Function1Extension.groovy
│ │ ├── Function2Extension.groovy
│ │ ├── OptionalExtension.groovy
│ │ └── OptionalStaticExtension.groovy
│ └── resources
│ └── META-INF
│ └── services
│ └── org.codehaus.groovy.runtime.ExtensionModule
├── kind
├── build.gradle
└── src
│ └── main
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ ├── FlatMap.groovy
│ ├── Free.groovy
│ ├── FreeP1.groovy
│ ├── FreeP1Monad.groovy
│ ├── Return.groovy
│ └── Suspend.groovy
├── main
├── build.gradle
└── src
│ ├── main
│ ├── groovy
│ │ └── com
│ │ │ └── github
│ │ │ └── mperry
│ │ │ └── fg
│ │ │ ├── CollectionExtension2.groovy
│ │ │ ├── CollectionStaticExtension2.groovy
│ │ │ ├── Comprehension.groovy
│ │ │ ├── FutureExtension.groovy
│ │ │ ├── FutureMonad.groovy
│ │ │ ├── Generator.groovy
│ │ │ ├── IOConstants.groovy
│ │ │ ├── Identity.groovy
│ │ │ ├── IdentityM.groovy
│ │ │ ├── IdentityMonad.groovy
│ │ │ ├── Lens.groovy
│ │ │ ├── ListMonadExtension.groovy
│ │ │ ├── ListMonadStaticExtension.groovy
│ │ │ ├── RandStateInteger.groovy
│ │ │ ├── ReaderM.groovy
│ │ │ ├── SetExtension2.groovy
│ │ │ ├── SetMonadExtension.groovy
│ │ │ ├── SetMonadStaticExtension.groovy
│ │ │ ├── SetStaticExtension2.groovy
│ │ │ ├── SimpleIO.java
│ │ │ ├── SimpleIOExtension.groovy
│ │ │ ├── SimpleIOStaticExtension.groovy
│ │ │ ├── SkiCalculus.groovy
│ │ │ ├── SqlExtension.groovy
│ │ │ ├── SqlExtensionJava.java
│ │ │ ├── State.groovy
│ │ │ ├── StateInt.groovy
│ │ │ ├── StateIntMonad.groovy
│ │ │ ├── StreamExtension2.groovy
│ │ │ ├── StreamStaticExtension2.groovy
│ │ │ ├── TypeLambda.groovy
│ │ │ ├── WriterM.groovy
│ │ │ ├── Yield.groovy
│ │ │ └── test
│ │ │ ├── DbcContractValidator.groovy
│ │ │ ├── MethodVerifier.groovy
│ │ │ ├── Model.groovy
│ │ │ └── Specification.groovy
│ └── resources
│ │ └── META-INF
│ │ └── services
│ │ └── org.codehaus.groovy.runtime.ExtensionModule
│ └── test
│ ├── groovy
│ └── com
│ │ └── github
│ │ └── mperry
│ │ └── fg
│ │ ├── ComprehensionTest.groovy
│ │ ├── FTest.groovy
│ │ ├── IdentityTest.groovy
│ │ ├── IdentityTest2.groovy
│ │ ├── LensTest.groovy
│ │ ├── LiftTest.groovy
│ │ ├── ListMonadTest.groovy
│ │ ├── ListTest.groovy
│ │ ├── MonadLaws.groovy
│ │ ├── ObjectTest.groovy
│ │ ├── OptionMonadTest.groovy
│ │ ├── ReaderTest.groovy
│ │ ├── SimpleIOTest.groovy
│ │ ├── SqlTest.groovy
│ │ ├── StackOverflowTest.groovy
│ │ ├── StateDynamicMonadTest.groovy
│ │ ├── StateIntDynamicMonadTest.groovy
│ │ ├── StateIntMonadTest.groovy
│ │ ├── StateTest.groovy
│ │ ├── StreamStaticExtension2Test.groovy
│ │ ├── StreamTest.groovy
│ │ ├── WriterTest.groovy
│ │ ├── euler
│ │ ├── P01.groovy
│ │ ├── P02.groovy
│ │ ├── P03.groovy
│ │ ├── P04.groovy
│ │ └── P05.groovy
│ │ └── test
│ │ ├── AdditionCommutesTest.groovy
│ │ ├── IntegerOverflow.groovy
│ │ ├── ListFunctorLawsTest.groovy
│ │ ├── ListTest.groovy
│ │ └── dbc
│ │ ├── ExceptionFreeStack.groovy
│ │ ├── ExceptionFreeStackTest.groovy
│ │ ├── TotalStack.groovy
│ │ └── TotalStackTest.groovy
│ └── resources
│ └── lift.properties
├── sandbox
├── build.gradle
└── src
│ ├── main
│ └── groovy
│ │ └── com
│ │ └── github
│ │ └── mperry
│ │ ├── A.groovy
│ │ └── B.groovy
│ └── test
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── TestCoercion.groovy
├── settings.gradle
├── test-extensions
├── build.gradle
└── src
│ └── test
│ └── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ ├── ListMonadExtensionTest.groovy
│ ├── OptionMonadExtensionTest.groovy
│ ├── SetMonadExtensionTest.groovy
│ └── test
│ └── ListJavaExtensionTest.groovy
└── typeclass
├── build.gradle
└── src
├── main
└── groovy
│ └── com
│ └── github
│ └── mperry
│ └── fg
│ └── typeclass
│ ├── Applicative.groovy
│ ├── Comonad.groovy
│ ├── Functor.groovy
│ ├── Monad.groovy
│ ├── MonadPlus.groovy
│ ├── MonadTrans.groovy
│ ├── Monoid.groovy
│ ├── Semigroup.groovy
│ └── concrete
│ ├── IOMonad.groovy
│ ├── ListApplicative.groovy
│ ├── ListFunctor.groovy
│ ├── ListMonad.groovy
│ ├── OptionApplicative.groovy
│ ├── OptionFunctor.groovy
│ ├── OptionMonad.groovy
│ ├── OptionMonadTrans.groovy
│ ├── OptionT.groovy
│ ├── SafeIOMonad.groovy
│ ├── SetMonad.groovy
│ ├── StateInt.groovy
│ └── StateIntMonad.groovy
└── test
└── groovy
└── com
└── github
└── mperry
└── fg
└── typeclass
├── FunctorTest.groovy
├── IOMonadTest.groovy
├── ListApplicativeTest.groovy
├── ListFunctorTest.groovy
├── MonadTransTest.groovy
├── OptionApplicativeTest.groovy
└── OptionMonadTest.groovy
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 | text eol=lf
4 |
5 | # Custom for Visual Studio
6 | *.cs diff=csharp
7 | *.sln merge=union
8 | *.csproj merge=union
9 | *.vbproj merge=union
10 | *.fsproj merge=union
11 | *.dbproj merge=union
12 |
13 | # Standard to msysgit
14 | *.doc diff=astextplain
15 | *.DOC diff=astextplain
16 | *.docx diff=astextplain
17 | *.DOCX diff=astextplain
18 | *.dot diff=astextplain
19 | *.DOT diff=astextplain
20 | *.pdf diff=astextplain
21 | *.PDF diff=astextplain
22 | *.rtf diff=astextplain
23 | *.RTF diff=astextplain
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | #.gitignore
3 | .gradle
4 | classes
5 | workspace.xml
6 | .idea
7 | *.iml
8 | out
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 |
2 | # http://lint.travis-ci.org/
3 | language: groovy
4 |
5 | sudo: false
6 |
7 | jdk:
8 | - oraclejdk8
9 |
10 | env:
11 | - secure: "Xv6ITZIEX+0wrev44Tzkg76oIzVYK2uOTb+Iubx/syhi9pyeA8MXhg6np7rV62bEs0KsXSygjdlYPlJKx5Gzq4e7MZQ/TZjC5Niu37tpRrI5Gc2f33I/VlYWvvKKoQzGgNf13oOAWHt84Vchk6zdJINLq71nRk+921fO7Ssl3VE="
12 | - secure: "tXjIV6JUt+1gKfL0qYzyY4jzbJG6kk32f7RmQn3vYmJXLxgNBnCDkOQ9GkJuiBld8GG2nsvAY4m34LmaxJzKzA/bZNzdkT7427ozAaGsQSRHHyc+/2UGOw/T3K3zF02h0W++yVTNHWuzXHCkitAlsw7esp9u97FdhqP08vzMLC0="
13 |
14 |
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Functional Groovy
2 | =================
3 |
4 | [Functional Groovy](https://github.com/mperry/functionalgroovy) is a library for doing functional programming
5 | (FP) in Groovy. It is a Groovy extension module for [Functional Java](https://functionaljava.github.io/) (FJ), adding Groovy idioms and new FP constructs in Groovy.
6 |
7 | Features includes:
8 | * FunctionalJava based
9 | * Enhances FunctionalJava for Groovy as a Groovy extension module
10 | * Groovy Quickcheck style property testing (specification based testing)
11 | * Monad library using a minimal monad implementation (unit/flatMap)
12 | * Monadic functions added to the standard Java List
13 | * Monad comprehensions (dynamically typed)
14 | * Lenses
15 | * Reader, Writer and State monads
16 | * A simple IO type
17 | * Y Combinator
18 |
19 | The project has some cloud build servers I used to experiment with including:
20 | * [Cloudbees Jenkins Build](https://mperry.ci.cloudbees.com/job/functionalgroovy/)
21 | * [Sonatype Functional Groovy Artifacts](https://oss.sonatype.org/content/groups/public/com/github/mperry/)
22 | * [Travis CI Build](https://travis-ci.org/mperry/functionalgroovy/builds)
23 |
24 | I have written an initial blog post on [Groovy Null Handling using Bind, Comprehensions and Lift](http://mperry.github.io/2013/07/28/groovy-null-handling.html) covering:
25 | * some introductory material on functional programming in Groovy
26 | * how to begin using the Functional Groovy library
27 | * handling `null`s by binding through the `Option` type, monadic comprehensions and monadic lifting
28 |
29 | The full list of related posts are:
30 | * [Groovy Null Handling Using Bind, Comprehensions and Lift](http://mperry.github.io/2013/07/28/groovy-null-handling.html)
31 | * [Specification Based Testing](http://mperry.github.io/2013/12/09/specification-based-testing.html)
32 | * [Referentially Transparent Input/Output in Groovy](http://mperry.github.io/2014/01/03/referentially-transparent-io.html)
33 | * [Folds and Unfolds](http://mperry.github.io/2014/01/21/folds-and-unfolds.html)
34 |
35 | To start using the library add the dependency `com.github.mperry:functionalgroovy-main:0.5.1-SNAPSHOT` to your Gradle
36 | project. A simple test script to get going (`test.groovy`) is:
37 |
38 | ```groovy
39 | @GrabResolver('https://oss.sonatype.org/content/groups/public')
40 | @Grab('com.github.mperry:functionalgroovy-core:0.5.1-SNAPSHOT')
41 | @Grab('org.functionaljava:functionaljava:4.1')
42 |
43 | import com.github.mperry.fg.*
44 |
45 | 1.to(5).each {
46 | println it
47 | }
48 | ```
49 |
50 | Run this script using `groovy test.groovy`.
51 |
52 | This project uses:
53 | * JDK 8
54 | * Gradle 1.11
55 | * Groovy 2.3.2
56 | * Functional Java 4.1
57 | * Intellij Community Edition 13.1
58 |
59 | I have added a list of [open issues](https://github.com/mperry/functionalgroovy/issues?state=open) so feel free to
60 | contribute. Some ways of contributing are:
61 | * adding new functionality
62 | * adding tests
63 | * adding FP in Groovy examples
64 | * adding FunctionalGroovy usage examples
65 |
66 | Functional Groovy is divided into four components: core, main, demo, java8 and consume.
67 | * Core enhances Functional Java with Groovy idioms
68 | * Main adds new functionality
69 | * Demo includes examples of FP in Groovy and usage of this library
70 | * Java8 includes enhancements related to Java 8 types (e.g. Optional).
71 | * Consume shows how to include FunctionalGroovy in your project
72 |
--------------------------------------------------------------------------------
/base/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | ext {
3 |
4 | }
5 |
6 | uploadArchives.enabled = true
7 |
8 | dependencies {
9 | compile gradleGroovy
10 | compile gradleFj
11 | compile project(":core")
12 |
13 | testCompile gradleJunit
14 | }
15 |
16 |
17 |
--------------------------------------------------------------------------------
/base/src/main/groovy/com/github/mperry/fg/YCombinator.groovy:
--------------------------------------------------------------------------------
1 | package com.github.mperry.fg
2 |
3 | import groovy.transform.TypeChecked
4 |
5 | /**
6 | * Created by MarkPerry on 23/01/14.
7 | */
8 | //@TypeChecked
9 | class YCombinator {
10 |
11 | /**
12 | * Strict applicative order Y combinator
13 | *
14 | * (define Y
15 | * (lambda (f)
16 | * ((lambda (x) (x x))
17 | * (lambda (x) (f (lambda (y) ((x x) y)))))))
18 | *
19 | * @param fx
20 | * @return
21 | */
22 | static def Y(Closure f) {
23 | def h = { Closure x ->
24 | // y is the value passed in
25 | f { y ->
26 | x(x)(y)
27 | }
28 | }
29 | h(h)
30 | }
31 |
32 | static def Y2(def f) {
33 | f({ x -> Y2(f)(x)})
34 |
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/base/src/test/groovy/com/github/mperry/fg/YCombinatorTest.groovy:
--------------------------------------------------------------------------------
1 | package com.github.mperry.fg
2 |
3 | import groovy.transform.TypeChecked
4 | import org.junit.Assert
5 | import org.junit.Test
6 |
7 | import static org.junit.Assert.assertTrue
8 |
9 | /**
10 | * Created by MarkPerry on 23/01/14.
11 | */
12 | //@TypeChecked
13 | class YCombinatorTest {
14 |
15 | @Test
16 | void testFib() {
17 | Closure fib = { Closure f ->
18 | { int n ->
19 | n < 2 ? n : f(n - 1) + f(n - 2)
20 | }
21 | }
22 | def f = YCombinator.Y2(fib)
23 | def x = f(6)
24 |
25 | println x
26 | Assert.assertTrue(x == 8)
27 | }
28 |
29 | @Test
30 | void testFactorial() {
31 | def fact = { Closure f ->
32 | { int n ->
33 | n == 1 ? n : n * f(n - 1)
34 | }
35 | }
36 | def f = YCombinator.Y(fact)
37 | def z = f(4)
38 | println z
39 | assertTrue(z == 24)
40 | // f(100)
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/consume/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | repositories {
3 |
4 | mavenCentral()
5 | maven {
6 | url sonatypeRepositoryUrl
7 | }
8 | }
9 |
10 | ext {
11 |
12 | }
13 |
14 | dependencies {
15 | compile gradleGroovy
16 | compile gradleFj
17 | compile "$groupName:$projectName-main:$consumeVersion"
18 | testCompile gradleJunit
19 | }
20 |
--------------------------------------------------------------------------------
/consume/scripts/bugImplicitBoxing.groovy:
--------------------------------------------------------------------------------
1 |
2 | @GrabResolver('https://oss.sonatype.org/content/repositories/snapshots/')
3 | @Grab('com.github.mperry:functionalgroovy-main:0.5-SNAPSHOT')
4 |
5 | import groovy.transform.TypeChecked
6 | import org.junit.Test
7 |
8 | import static junit.framework.Assert.assertTrue
9 |
10 | @TypeChecked
11 | class StreamTest {
12 |
13 | @Test
14 | void explicitBox() {
15 | assertTrue(new Integer(1).to(3).toJavaList() == (1..3).toList())
16 | }
17 |
18 | @Test
19 | void implicitBox() {
20 | // fails with error:
21 |
22 | /*
23 | Caught: BUG! exception in phase 'instruction selection' in source unit 'D:\repositories\functionalgroovy\consume\scripts\stream.groovy' Declaring class for method call to 'fj.data.Stream to(java.lang.Integer, java.lang.Integer)' declared in java.lang.Integer was not matched with found receiver int. This should not have happened!
24 |
25 | BUG! exception in phase 'instruction selection' in source unit 'D:\repositories\functionalgroovy\consume\scripts\stream.groovy' Declaring class for method call to 'fj.data.Stream to(java.lang.Integer, java.lang.Integer)' declared in java.lang.Integer was not matched with found receiver int. This should not have happened!
26 |
27 | */
28 |
29 | // comment out this test to demonstrate that the explicit boxing test
30 | // above works
31 | assertTrue(1.to(3).toJavaList() == (1..3).toList())
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/consume/scripts/exceptionHandling.groovy:
--------------------------------------------------------------------------------
1 | @GrabResolver(name='custom', root='https://oss.sonatype.org/content/groups/public', m2Compatible=true)
2 | //@Grab('org.functionaljava:functionaljava:4.2-SNAPSHOT')
3 | @Grab('com.github.mperry:functionalgroovy-core:0.6-SNAPSHOT')
4 |
5 | import fj.*
6 | import fj.data.*
7 | import groovy.transform.TypeChecked
8 | import org.junit.Test
9 |
10 | /**
11 | * Created by mperry on 4/08/2014.
12 | */
13 | @TypeChecked
14 | class ExceptionHandling {
15 |
16 | Validation extends IOException, String> contents(String s) {
17 | ({ -> (new URL(s)).text } as P1).validate()
18 | }
19 |
20 | Validation extends IOException, String> contents2(String s) {
21 | P.lazy({ -> (new URL(s)).text } as P1).validate()
22 | }
23 |
24 | @Test
25 | void errorTest() {
26 | def actual = ["malformed", "http://www.this-page-intentionally-left-blank.org/"].collect { String s ->
27 | contents2(s).isSuccess()
28 | }
29 | assert actual == [false, true]
30 | }
31 |
32 | }
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/consume/scripts/genericTypeCheck.groovy:
--------------------------------------------------------------------------------
1 |
2 | // does not type check with Groovy 2.3.0-rc-4
3 |
4 | import groovy.transform.TypeChecked
5 | //import org.junit.Test
6 |
7 | @TypeChecked
8 | class Class1 {
9 |
10 | static void method1(A a, B b) {
11 | method2(a, b)
12 | }
13 |
14 | static void method2(A a, B b) {
15 | }
16 |
17 | static void method3(List list1, List list2) {
18 | method1(list1.get(0), list2.get(0))
19 | }
20 |
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/consume/scripts/optionMonadTest.groovy:
--------------------------------------------------------------------------------
1 |
2 |
3 | // from https://github.com/mperry/functionalgroovy/blob/master/test-extensions/src/test/groovy/com/github/mperry/fg/OptionMonadExtensionTest.groovy
4 |
5 | //@GrabResolver('https://oss.sonatype.org/content/groups/public')
6 | @GrabResolver('https://oss.sonatype.org/content/repositories/snapshots/')
7 | @Grab('com.github.mperry:functionalgroovy-main:0.5-SNAPSHOT')
8 | import fj.F
9 | import fj.F2
10 | import fj.function.Integers
11 | import groovy.transform.TypeChecked
12 | import org.junit.Test
13 | import com.github.mperry.fg.typeclass.concrete.OptionMonad
14 |
15 | import static fj.Function.uncurryF2
16 | import static fj.data.Option.none
17 | import static fj.data.Option.some
18 | import static junit.framework.Assert.assertTrue
19 |
20 | @TypeChecked
21 | class OptionMonadTest {
22 |
23 | OptionMonad monad() {
24 | new OptionMonad()
25 | }
26 |
27 | @Test
28 | void ap() {
29 | def f = { Integer i -> i + 1} as F
30 | assertTrue(monad().ap(some(1), some(f)) == some(2))
31 | assertTrue(monad().ap(some(1), none()) == none())
32 | assertTrue(monad().ap(none(), some(f)) == none())
33 | }
34 |
35 | @Test
36 | void filterM() {
37 | def f = { Integer i -> some(i > 0)} as F
38 | def actual = monad().filterM([2, 1, 0, -1], f)
39 | assertTrue(actual == some([2, 1]))
40 | }
41 |
42 | @Test
43 | void fmap() {
44 | def actual = monad().fmap(Integers.negate, some(1))
45 | assertTrue(actual == some(-1))
46 | }
47 |
48 | @Test
49 | void foldM() {
50 | def saveDiv = { BigDecimal n, Integer d -> d == 0 ? none() : some(n/d) } as F2
51 | assertTrue(monad().foldM([4, 5], 40.toBigDecimal(), saveDiv) == some(2.toBigDecimal()))
52 | assertTrue(monad().foldM([4, 0, 2], 40.toBigDecimal(), saveDiv) == none())
53 | }
54 |
55 | @Test
56 | void join() {
57 | assertTrue(monad().join(some(some(1))) == some(1))
58 | assertTrue(monad().join(some(none())) == none())
59 | assertTrue(monad().join(none()) == none())
60 | }
61 |
62 | @Test
63 | void liftM() {
64 | def f = Integers.negate
65 | assertTrue(monad().liftM(some(4), f) == some(-4))
66 | assertTrue(monad().liftM(none(), f) == none())
67 | }
68 |
69 | @Test
70 | void liftM2() {
71 | def f = uncurryF2(Integers.multiply)
72 | assertTrue(monad().liftM2(some(3), some(4), f) == some(12))
73 | assertTrue(monad().liftM2(some(3), none(), f) == none())
74 | assertTrue(monad().liftM2(none(), none(), f) == none())
75 | }
76 |
77 | @Test
78 | void sequence() {
79 | // println actual
80 | assertTrue(monad().sequence([some(2), some(3)]) == some([2, 3]))
81 | assertTrue(monad().sequence([some(2), none()]) == none())
82 | }
83 |
84 | @Test
85 | void replicateM() {
86 | assertTrue(monad().replicateM(4, some(3)) == some([3, 3, 3, 3]))
87 | assertTrue(monad().replicateM(3, none()) == none())
88 | }
89 |
90 | @Test
91 | void traverse() {
92 | def f = { Integer i -> i > 0 ? some(i) : none() } as F
93 | assertTrue(monad().traverse([2, -4, 6], f) == none())
94 | assertTrue(monad().traverse([2, 6], f) == some([2, 6]))
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/consume/scripts/test.groovy:
--------------------------------------------------------------------------------
1 |
2 | @GrabResolver('https://oss.sonatype.org/content/groups/public')
3 | @Grab('com.github.mperry:functionalgroovy-core:0.5-SNAPSHOT')
4 | @Grab('org.functionaljava:functionaljava:3.1')
5 |
6 | import com.github.mperry.fg.*
7 |
8 |
9 | 1.to(5).each {
10 | println it
11 | }
12 |
--------------------------------------------------------------------------------
/consume/src/test/groovy/com/github/mperry/fg/Example.groovy:
--------------------------------------------------------------------------------
1 | package com.github.mperry.fg
2 |
3 | import fj.F
4 | import groovy.transform.TypeChecked
5 | import org.junit.Test
6 |
7 | /**
8 | * Created with IntelliJ IDEA.
9 | * User: MarkPerry
10 | * Date: 13/12/13
11 | * Time: 4:12 PM
12 | * To change this template use File | Settings | File Templates.
13 | */
14 | @TypeChecked
15 | class Example {
16 |
17 | @Test
18 | void test1() {
19 | println "First FunctionalGroovy demo"
20 | 1.to(5).each {
21 | println it
22 | }
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/consume/src/test/groovy/com/github/mperry/fg/FutureTest.groovy:
--------------------------------------------------------------------------------
1 | package com.github.mperry.fg
2 |
3 | import fj.P1
4 | import fj.control.parallel.Promise
5 | import fj.control.parallel.Strategy
6 | import fj.data.Option
7 | import groovy.transform.TypeChecked
8 | import org.junit.Test
9 |
10 | import java.util.concurrent.Callable
11 | import java.util.concurrent.Executors
12 | import java.util.concurrent.Future
13 | import java.util.concurrent.FutureTask
14 |
15 | import static com.github.mperry.fg.test.Specification.specAssert
16 | import static org.junit.Assert.assertTrue
17 |
18 | /**
19 | * Created by MarkPerry on 17/04/2014.
20 | */
21 |
22 | @TypeChecked
23 | class FutureTest {
24 |
25 | Future future(String s) {
26 | Executors.newCachedThreadPool().submit(callable(s))
27 | }
28 |
29 | Callable callable(final String s) {
30 | new Callable() {
31 | @Override
32 | String call() throws Exception {
33 | Thread.sleep(100) // milliseconds
34 | s
35 | }
36 | }
37 | }
38 |
39 | Future task(final String s) {
40 | new FutureTask(callable(s))
41 | }
42 |
43 | P1