Skip to content

Commit

Permalink
Merge pull request #145 from Kevin-Lee/task/142/docs
Browse files Browse the repository at this point in the history
Task/142/docs
  • Loading branch information
kevin-lee committed Jan 9, 2020
2 parents c4b40bf + 8338df5 commit 061f21a
Show file tree
Hide file tree
Showing 18 changed files with 640 additions and 1 deletion.
47 changes: 47 additions & 0 deletions .github/workflows/publish-github-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Publish GitHub Pages

on:
pull_request:
branches:
- publish-docs

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1

- name: Cache Coursier
uses: actions/cache@v1
with:
path: ~/.cache/coursier
key: ${{ runner.os }}-coursier-scala-2_13-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('**/build.properties') }}
restore-keys: |
${{ runner.os }}-coursier-scala-2_13-
- name: Cache Ivy
uses: actions/cache@v1
with:
path: ~/.ivy2/cache
key: ${{ runner.os }}-ivy-scala-2_13-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('**/build.properties') }}
restore-keys: |
${{ runner.os }}-ivy-scala-2_13-
- name: publish GitHub Pages
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_AUTH_TOKEN }}
run: |
docker run \
-e GITHUB_TOKEN=$GITHUB_TOKEN \
-v ${{ github.workspace }}:/app \
-v ~/.cache/coursier:/root/.cache/coursier:z \
-v ~/.ivy2/cache:/root/.ivy2/cache:z \
k3vin/sbt-java8-jekyll:latest /bin/bash -c "cd /app && sbt 'project docs' clean publishMicrosite"
- name: correct dir permission
run: |
sudo chown -R $(whoami):docker ~/.ivy2
sudo chown -R $(whoami):docker ~/.cache
sudo chown -R $(whoami):docker ${{ github.workspace }}
46 changes: 45 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import ProjectInfo._
import kevinlee.sbt.SbtCommon.crossVersionProps
import just.semver.SemVer
import SemVer.{Major, Minor}
import microsites.ConfigYml

val ProjectScalaVersion: String = "2.13.1"
val CrossScalaVersions: Seq[String] = Seq("2.10.7", "2.11.12", "2.12.10", ProjectScalaVersion)
Expand Down Expand Up @@ -33,11 +34,12 @@ ThisBuild / scmInfo :=
def prefixedProjectName(name: String) = s"just-fp${if (name.isEmpty) "" else s"-$name"}"

lazy val justFp = (project in file("."))
.enablePlugins(DevOopsGitReleasePlugin)
.settings(
name := prefixedProjectName("")
, description := "Just FP Lib"
)
.dependsOn(core)
.dependsOn(core, docs)

lazy val core = (project in file("core"))
.enablePlugins(DevOopsGitReleasePlugin)
Expand Down Expand Up @@ -106,3 +108,45 @@ lazy val core = (project in file("core"))
})
/* } Coveralls */
)

lazy val docDir = file("docs")
lazy val docs = (project in docDir)
.enablePlugins(MicrositesPlugin)
.settings(
name := prefixedProjectName("docs")
/* microsites { */
, micrositeName := prefixedProjectName("")
, micrositeAuthor := "Kevin Lee"
, micrositeHomepage := "https://blog.kevinlee.io"
, micrositeDescription := "Just FP"
, micrositeGithubOwner := "Kevin-Lee"
, micrositeGithubRepo := "just-fp"
, micrositeBaseUrl := "/just-fp"
, micrositeDocumentationUrl := s"${micrositeBaseUrl.value}/docs"
, micrositePushSiteWith := GitHub4s
, micrositeGithubToken := sys.env.get("GITHUB_TOKEN")
, micrositeTheme := "pattern"
, micrositeHighlightTheme := "atom-one-light"
, micrositeGitterChannel := false
, micrositeGithubLinks := false
, micrositeShareOnSocial := false
, micrositeHighlightLanguages ++= Seq("shell")

, micrositeConfigYaml := ConfigYml(
yamlPath = Some(docDir / "microsite" / "_config.yml")
)
, micrositeImgDirectory := docDir / "microsite" / "img"
, micrositeCssDirectory := docDir / "microsite" / "css"
, micrositeSassDirectory := docDir / "microsite" / "sass"
, micrositeJsDirectory := docDir / "microsite" / "js"
, micrositeExternalLayoutsDirectory := docDir / "microsite" / "layouts"
, micrositeExternalIncludesDirectory := docDir / "microsite" / "includes"
, micrositeDataDirectory := docDir / "microsite" / "data"
, micrositeStaticDirectory := docDir / "microsite" / "static"
, micrositeExtraMdFilesOutput := docDir / "microsite" / "extra_md"
, micrositePluginsDirectory := docDir / "microsite" / "plugins"

/* } microsites */

)
.dependsOn(core)
33 changes: 33 additions & 0 deletions docs/docs/docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
layout: docs
title: Getting Started
---
# just-fp
[![Build Status](https://github.com/Kevin-Lee/just-fp/workflows/Build%20All/badge.svg)](https://github.com/Kevin-Lee/just-fp/actions?workflow=Build+All)
[![Release Status](https://github.com/Kevin-Lee/just-fp/workflows/Release/badge.svg)](https://github.com/Kevin-Lee/just-fp/actions?workflow=Release)
[![Coverage Status](https://coveralls.io/repos/github/Kevin-Lee/just-fp/badge.svg?branch=master)](https://coveralls.io/github/Kevin-Lee/just-fp?branch=master)

[![Download](https://api.bintray.com/packages/kevinlee/maven/just-fp/images/download.svg)](https://bintray.com/kevinlee/maven/just-fp/_latestVersion)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.kevinlee/just-fp_2.13/badge.svg)](https://search.maven.org/artifact/io.kevinlee/just-fp_2.13)
[![Latest version](https://index.scala-lang.org/kevin-lee/just-fp/just-fp/latest.svg)](https://index.scala-lang.org/kevin-lee/just-fp/just-fp)


just-fp is a small Functional Programming library. This is not meant to be an alternative to Scalaz or Cats. The reason for having this library is that in your project you don't want to have Scalaz or Cats as its dependency and you only need much smaller set of functional programming features than what Scalaz or Cats offers. So the users of your library can choose Scalaz or Cats to be used with your library.

# Getting Started
In `build.sbt`,

```scala
libraryDependencies += "io.kevinlee" %% "just-fp" % "1.3.5"
```
then import

```scala
import just.fp._
import just.fp.syntax._
```
or
```scala
import just.fp._, syntax._
```
In all the example code using `just-fp` below, I assume that you've already imported `just-fp` at the top.
120 changes: 120 additions & 0 deletions docs/docs/docs/syntax/either.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
layout: docs
title: Either
---

# Either

## Right-Biased `Either`
`Either` in Scala prior to 2.12 is not right-biased meaning that you have to call `Either.right` all the time if you want to use it with `for-comprehension`.

e.g.) Before 2.12
```scala
for {
b <- methodReturningEither(a).right
c <- anotherReturningEither(b).right
} yield c
```
If you use `just-fp`, it becomes

```scala mdoc
import just.fp.syntax._
```
```scala
for {
b <- methodReturningEither(a)
c <- anotherReturningEither(b)
} yield c
```
Of course, you don't need to do it if you use Scala 2.12 or higher.

## Either Constructors
In normal ways, if you want to create `Left` or `Right`, you just use the `apply` methods of their companion objects (i.e. `Left()` `Right()`) A problem with this is that what these return is not `Either` but its data, `Left` or `Right`.

You also need to specify not only type parameter for `Left` but also the one for `Right` when creating `Right`.

e.g.) Without type parameters,
```scala mdoc
Right(1)
```
You don't want to have `Nothing` there. So do it with type parameters,
```scala mdoc
Right[String, Int](1)
```
So it becomes unnecessarily verbose. Right should be inferred as the compiler knows it already yet to specify the left one, you have to put both left and right parameters.

`Left`, of course, has the same problem.

```scala mdoc
Left("error")
```
```scala mdoc
Left[String, Int]("error")
```

Now with `just-fp`, it's simpler. You can use use `left` and `right` constructors as extension methods to the actual data values with only missing type info specified.

e.g.)
```scala mdoc
1.right[String] // Now you only need to specify
// the missing type info only
// that is Left type parameter.
```
For `Left`,
```scala mdoc
"error".left[Int]
```

## `leftMap` and `leftFlatMap`
So if you Scala 2.12 or higher or `just-fp` with the older Scala, `Either` is right-biassed. Then what about the `Left` case? Can I ever use `Left` for something useful like transforming the `Left` value to something else?

For that, `just-fp` has added `leftMap` and `leftFlatMap` to `Either`.
e.g.)
```scala mdoc:reset-object
import just.fp.syntax._

final case class ComputeError(error: String)

sealed trait AppError
object AppError {
final case class InvalidNumberError(error: String) extends AppError
final case class ComputationError(computeError: ComputeError) extends AppError

def invalidNumberError(error: String): AppError =
InvalidNumberError(error)
def fromComputeError(computeError: ComputeError): AppError =
ComputationError(computeError)
}

def f1(n: Int): Either[String, Int] =
if (n < 0)
Left(s"The number must be non-negative integer - n: $n")
else
Right(n)

def f2(x: Int, y: Int): Either[ComputeError, Int] = {
val z = x + y
if (x >= 0 && y >= 0 && z < 0)
Left(ComputeError(s"Numbers are too big - x: $x, y: $y"))
else
Right(x + y)
}
```
```scala mdoc
for {
b <- f1(10).leftMap(AppError.invalidNumberError)
c <- f2(123, b).leftMap(AppError.fromComputeError)
} yield c
```
```scala mdoc
for {
b <- f1(-1).leftMap(AppError.invalidNumberError)
c <- f2(123, b).leftMap(AppError.fromComputeError)
} yield c
```
```scala mdoc
for {
b <- f1(Int.MaxValue).leftMap(AppError.invalidNumberError)
c <- f2(1, b).leftMap(AppError.fromComputeError)
} yield c
```
9 changes: 9 additions & 0 deletions docs/docs/docs/syntax/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
layout: docs
title: Syntax
---
# Syntax

* [Either](either)
* [Option](option)
* [Type-safe Equal](type-safe-equal)
30 changes: 30 additions & 0 deletions docs/docs/docs/syntax/option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
layout: docs
title: Option
---

# Option
## Option Constructors
Similar to `Either`, creating `Option` can expose its data instead of type.

e.g.) The following code returns `Some[Int]` not `Option[Int]`.
```scala mdoc
Some(1)
```

Also None is None not `Option[A]`.
```scala mdoc
None
```

With `just-fp`,

```scala mdoc
import just.fp.syntax._
```
```scala mdoc
1.some
```
```scala mdoc
none[String]
```
66 changes: 66 additions & 0 deletions docs/docs/docs/syntax/type-safe-equal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
layout: docs
title: Type-safe Equal
---

# Type-safe Equal
`==` in Scala is not type safe so the following code can never be `true` as their types are different but it has no compile-time error.

```scala
1 == "1" // always false, no compile-time error
```

`just-fp` has `Equal` typeclass with typeclass instances for value types (`Byte`, `Short`, `Int`, `Char`, `Long`, `Float` and `Double`) as well as `String`, `BigInt` and `BigDecimal`.

It also has `Equal` typeclass instances for `WriterT`, `Writer` and `EitherT`.

With `just-fp`,

```scala mdoc
import just.fp.syntax._
```
```scala mdoc:fail
// use triple equals from just-fp
1 === "1"
```
```scala mdoc
1 === 1

"a" === "a"

1 !== 1

1 !== 2
```

If it's a `case class` the `equals` of which can be used for equality check, `NatualEqual` can be used.

e.g.)
```scala mdoc:reset-object:fail
final case class Foo(n: Int)

Foo(1) === Foo(1)
```
This can be solved by `NatualEqual.equalA[A]`.

```scala mdoc:reset-object
import just.fp._, syntax._

final case class Foo(n: Int)

object Foo {
implicit val eqaul: Equal[Foo] = Equal.equalA[Foo]
}

Foo(1) === Foo(1)
// Boolean = true

Foo(1) === Foo(2)
// Boolean = false

Foo(1) !== Foo(1)
// Boolean = false

Foo(1) !== Foo(2)
// Boolean = true
```
5 changes: 5 additions & 0 deletions docs/docs/docs/typeclass/applicative.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: docs
title: Applicative
---
# Applicative
5 changes: 5 additions & 0 deletions docs/docs/docs/typeclass/either-t.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: docs
title: EitherT
---
# EitherT
5 changes: 5 additions & 0 deletions docs/docs/docs/typeclass/functor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
layout: docs
title: Functor
---
# Functor

0 comments on commit 061f21a

Please sign in to comment.