Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add spec method to Exact #20

Merged
merged 6 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 45 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Module Arrow Exact
# Arrow Exact

Arrow Exact allows you to use Kotlin's type system to enforce exactness of data structures.

Expand All @@ -11,17 +11,19 @@ example easily create a `NotBlankString` type that is a `String` that is not bla
the Arrow's `Raise` DSL to `ensure` the value is not blank.

```kotlin
import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankString(raw)
}
}
}
```

Expand All @@ -48,31 +50,54 @@ Either.Left(ExactError(message=Cannot be blank.))
<!--- KNIT example-readme-01.kt -->
<!--- TEST -->

You can also define `Exact` by using Kotlin delegation.
<!--- INCLUDE
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
-->
```kotlin
@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by Exact({
ensure(it.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(it)
})
}
```
<!--- KNIT example-readme-02.kt -->

You can define a second type `NotBlankTrimmedString` that is a `NotBlankString` that is also
trimmed. Since the `exact` constructor allows us to compose `Exact` instances, we can easily
trimmed. Since the `ensure` allows us to compose `Exact` instances, we can easily
reuse the `NotBlankString` type.
<!--- INCLUDE
import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact
import arrow.exact.ensure

@JvmInline value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankString(raw)
}
}
}
-->

```kotlin
@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({
val notBlank = ensure(NotBlankString)
NotBlankTrimmedString(notBlank.value.trim())
})
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankTrimmedString {
ensure(raw, NotBlankString)
return NotBlankTrimmedString(raw.trim())
}
}
}
```

<!--- KNIT example-readme-02.kt -->
<!--- KNIT example-readme-03.kt -->
12 changes: 7 additions & 5 deletions guide/src/commonMain/kotlin/examples/example-exact-01.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// This file was automatically generated from Exact.kt by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleExact01

import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
companion object : Exact<String, NotBlankString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankString(raw)
}
}
}

fun example() {
Expand Down
16 changes: 4 additions & 12 deletions guide/src/commonMain/kotlin/examples/example-exact-02.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@ package arrow.exact.knit.example.exampleExact02
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}

@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({
val notBlank = ensure(NotBlankString)
NotBlankTrimmedString(notBlank.value.trim())
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by Exact({
ensure(it.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(it)
})
}
39 changes: 16 additions & 23 deletions guide/src/commonMain/kotlin/examples/example-exact-03.kt
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
// This file was automatically generated from Exact.kt by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleExact03

import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactEither
import arrow.exact.ExactError
import arrow.exact.exact
import arrow.exact.exactEither
import arrow.exact.ensure

@JvmInline value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankTrimmedString(raw.trim())
})
}

sealed interface UsernameError {
object Invalid : UsernameError
data class Offensive(val username: String) : UsernameError
class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankString(raw)
}
}
}

@JvmInline
value class Username private constructor(val value: String) {
companion object : ExactEither<UsernameError, String, Username> by exactEither({
val username =
ensure(NotBlankTrimmedString) {
UsernameError.Invalid
}.value
ensure(username.length < 100) { UsernameError.Invalid }
ensure(username !in listOf("offensive")) { UsernameError.Offensive(username) }
Username(username)
})
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankTrimmedString {
ensure(raw, NotBlankString)
return NotBlankTrimmedString(raw.trim())
}
}
}
39 changes: 39 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-exact-04.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// This file was automatically generated from Exact.kt by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleExact04

import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactEither
import arrow.exact.ExactError
import arrow.exact.ensure

@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankTrimmedString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankTrimmedString(raw.trim())
}
}
}

sealed interface UsernameError {
object Invalid : UsernameError
data class Offensive(val username: String) : UsernameError
}

@JvmInline
value class Username private constructor(val value: String) {
companion object : ExactEither<UsernameError, String, Username> {
override fun Raise<UsernameError>.spec(raw: String): Username {
val username =
ensure(raw, NotBlankTrimmedString) {
UsernameError.Invalid
}.value
ensure(username.length < 100) { UsernameError.Invalid }
ensure(username !in listOf("offensive")) { UsernameError.Offensive(username) }
return Username(username)
}
}
}
14 changes: 8 additions & 6 deletions guide/src/commonMain/kotlin/examples/example-readme-01.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// This file was automatically generated from README.md by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleReadme01

import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankString(raw)
}
}
}

fun example() {
Expand Down
18 changes: 5 additions & 13 deletions guide/src/commonMain/kotlin/examples/example-readme-02.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@ package arrow.exact.knit.example.exampleReadme02
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.exact

@JvmInline value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by exact({
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(raw)
})
}

@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> by exact({
val notBlank = ensure(NotBlankString)
NotBlankTrimmedString(notBlank.value.trim())
})
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> by Exact({
ensure(it.isNotBlank()) { ExactError("Cannot be blank.") }
NotBlankString(it)
})
}
28 changes: 28 additions & 0 deletions guide/src/commonMain/kotlin/examples/example-readme-03.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This file was automatically generated from README.md by Knit tool. Do not edit.
package arrow.exact.knit.example.exampleReadme03

import arrow.core.raise.Raise
import arrow.core.raise.ensure
import arrow.exact.Exact
import arrow.exact.ExactError
import arrow.exact.ensure

@JvmInline
value class NotBlankString private constructor(val value: String) {
companion object : Exact<String, NotBlankString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankString {
ensure(raw.isNotBlank()) { ExactError("Cannot be blank.") }
return NotBlankString(raw)
}
}
}

@JvmInline
value class NotBlankTrimmedString private constructor(val value: String) {
companion object : Exact<String, NotBlankTrimmedString> {
override fun Raise<ExactError>.spec(raw: String): NotBlankTrimmedString {
ensure(raw, NotBlankString)
return NotBlankTrimmedString(raw.trim())
}
}
}
Loading