そうだARROWを入れてみよう
Tags: arrowkt, kotlin, android
Published: 2018-09-17 06:02:31

---
title: そうだARROWを入れてみよう
published: true
description: これからARROWを触ってみたいけど、周りにARROWを触っている人が居ない…とかそんな人向け
tags: arrowkt,kotlin,android
---

ARROWを触ってみたいけど、周りにARROWを触っている人が居ない…とかそんな（どんな）人向け

## 結論

公式DocumentのBeginnerタグ（？）ついているのを読むとか。

[Option](https://arrow-kt.io/docs/datatypes/option/)
[Either](https://arrow-kt.io/docs/datatypes/either/)
[Try](https://arrow-kt.io/docs/datatypes/try/)

あとは試しに使ってみて…大丈夫ほら、一回だけなら…

ってことで、最初にこの辺知ってたら楽しいかも？みたいなのを雑に紹介。

## Option

kotlinのNullSafety(というかNullableというか)は便利だけどなぁ…
というあなたのために。

「NullSafety(というかNullableというか)じゃだめなの？？」という人は「Nullable Option」とかでググると色々な記事が出てくると思いますので、
なるほど！！ってなった場合に特におすすめです（ここでのチャーンレート高そうだ）

アプローチが違うというか…でもほら、一回使ってみるだけなら…

```kotlin
fun <A> convertSample(src:A?) {
    val a:Option<A> = Option.fromNullable(src)
    val b:Option<A> = src.toOption()
}

fun <A> convertSampleFromNonNull(src:A) {
    convertSample(src)
    val a:Option<A> = Option(src)
    val b:Option<A> = Option.just(src)
    val c:Option<A> = src.some()
}
```

といろいろとありますが、まあtoOption()で統一しておけば良いんじゃないでしょうか？

チョット特殊例？
[FunctionalJavaでOption#iif](https://github.com/functionaljava/functionaljava/blob/v4.8/core/src/main/java/fj/data/Option.java#L726)とか使っていた人向け
いやまあそんな人がこのブログ見て得られるものってあるのかというのは置いといて…

```kotlin
fun condition(...):Boolean = ...

fun returnValue():A

val a:Option<A> = condition(...).maybe{ returnValue() }

```

[Booleanにmaybeという拡張関数が生えている](https://github.com/arrow-kt/arrow/blob/0.7.3/modules/core/arrow-core/src/main/kotlin/arrow/core/Option.kt#L204)で、そちらで

### 例

```kotlin
fun <A, B, C> nonErrorMethod(a: A, b: B, c: C): Result {
    // エラーも副作用もないような処理
}

fun <A, B, C> kotlinSample(a: A?, b: B?, c: C?) {

    val result1: Result? = if (a != null && b != null && c != null) {
        nonErrorMethod(a, b, c)
    } else {
        null
    }

    val result2: Result? = a?.let { nonNullA ->
        b?.let { nonNullB ->
            c?.let { nonNullC ->
                nonErrorMethod(nonNullA, nonNullB, nonNullC)
            }
        }
    }
}

fun <A, B, C> useArrowSample(a: A?, b: B?, c: C?) {
    val optionA = a.toOption()
    val optionB = b.toOption()
    val optionC = c.toOption()
    
    val result1:Option<Result> = optionA.flatMap { nonNullA ->
        optionB.flatMap { nonNullB ->
            optionC.map{ nonNullC ->
                nonErrorMethod(nonNullA, nonNullB, nonNullC)
            }
        }
    }

    val result2: Option<Result> = Option.monad().binding {
        val a:A = optionA.bind()
        val b:B = optionB.bind()
        val c:C = optionC.bind()

        nonErrorMethod(a, b, c)
    }.fix()


    val result3: Option<Result> = Option.applicative()
        .map(optionA, optionB, optionC) { (a, b, c) -> nonErrorMethod(a, b, c) }.fix()
}
```

多分だいたいこんな感じでしょう。
何れの場合も引数の何れかがNull/Noneの場合、結果もNull/Noneになりますね。

monadとかapplicativeとか出てきていますが、
一旦は↑のサンプルみたいな挙動をするようになる便利な構文…で良いと思います。
特に前者はScala使っている人とかにはfor式チックなやつ…とかで…

具体的には

```
Option.monad().binding{...}.fix()でくくると、
... の中でOption<X>に対して.bind()ってメソッドが生える
呼ぶとOptionがNoneだったら処理を抜けてNoneを返し
SomeだったらXを返して次へ進む

Option.applicative()(aOption,bOption,cOption,..., {(a,b,c,...) -> ... }).fix()
で、aOption,bOptino,cOption,... の全部がSomeだった場合だけ、最後の引数で渡したメソッドが実行される
```

みたいな。

怖い人に怒られそうだけど、そんな感じで良いと思います。

### reference

下記にもっと書いてある
https://arrow-kt.io/docs/datatypes/option/

## Either

個人的な印象なのですが、LiveDataとかObservable各種を使っていると、
この手のものを自前で実装する(したくなる)ケースが多いと思います。
成功時だけじゃなくて失敗時も伝搬させたい…みたいな

例えば[このへんのSlideだったり](https://speakerdeck.com/ryugoo/either-dexiang-ding-nei-falseeratoxiang-ding-wai-falseerawobie-mofalsenisitai)

そんなあなたのために、ちゃんと用意されています。

### 例

```kotlin

sealed class MyError(val msg:String)
object MyError1 : MyError("error 1")
object MyError2 : MyError("error 2")

val liveData:LiveData<Either<MyError, Result>> = MutableLiveData()

liveData.observe(..., Observer{ either ->
    handlingSample(either)
})

fun handlingSample(either: Either<MyError, Result>) {
    val result1: String = either.fold(
        {
            error ->    
            error.msg
        },
        {
            res ->
            "success"
        }
    )
    
    val result2: String = when (either) {
        is Either.Left -> when (either.a) {
            MyError1 -> "MyError1 ${either.a}"
            MyError2 -> "MyError2 ${either.a}"
        }
        is Either.Right -> "success"
    }
}

fun aEither():Either<MyError, A>
fun bEither():Either<MyError, B>
fun cEither():Either<MyError, C>

fun useArrowSample() {

    val result1 = aEither().flatMap { a ->
        bEither().flatMap { b ->
            cEither().map { c ->
                nonErrorMethod(a, b, c)
            }
        }
    }

    val result2: Either<MyError, Result> = Either.monad<MyError>().binding {
        val a = aEither().bind()
        val b = bEither().bind()
        val c = cEither().bind()
        nonErrorMethod(a, b, c)
    }.fix()

    val result3: Either<MyError, Result> =
            Either.applicative<MyError>().map(aEither(), bEither(), cEither()) { (a, b, c) -> nonErrorMethod(a, b, c) }.fix()
}

```

上の方はLiveDataでエラーのときもなんかしたい（この場合タダStringにまるめているだけですが…）とかの雑なサンプルを

後半部分は、なんかOptionの時とよく似てますね？

これ素直なKotlinで書くってなるとどう書くんでしょうか…
LiveDataとかで伝搬させるためのクラスを作る感じになると思うので、[GoogleSamplesとかだとこの辺とか…？](https://github.com/googlesamples/android-architecture-components/blob/724cc1bd6ed11171a0bbf4a3a29977fac053777e/GithubBrowserSample/app/src/main/java/com/android/example/github/api/ApiResponse.kt)

### reference

下記にもっと色々と書いてある
https://arrow-kt.io/docs/datatypes/either/


## Try

似たようなので（？）[1.3-M1でSuccessOrFailureとか](https://blog.jetbrains.com/kotlin/2018/07/see-whats-coming-in-kotlin-1-3-m1/)あるけどなんかこれ…
`we discourage using SuccessOrFailure as return type of functions` ってことらしいし
[この方のコメントで言われているぐらいに捉えたほうが納得するというか？](https://github.com/Kotlin/KEEP/issues/127#issuecomment-406789929)
`This SuccessOrFailure class SHOULD NOT be used directly as a return type only in case the failure is handled by the caller locally. Where nullable type and sealed class hierarchy could be used instead.`
[そうすればこの辺の構文がわからんでもないというか...](https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/success-or-failure.md#api-details)

いやまあ使ってわかりやすいのかこれ…

まあ1.3でたらわかるでしょうし、長いものには巻かれます。
[ちなみにM2で触れられているContractsのほうが気になっていますし、欲しい。](https://blog.jetbrains.com/kotlin/2018/08/kotlin-1-3-m2/)

Contracts構文素敵じゃないですか？
Internalでは1.1か2くらいから使われていたんだし、はよ出してくれ。

### 例

多分もう想像つくかと

```kotlin

sealed class MyError(val msg:String): Throwable(msg)
object MyError1 : MyError("error 1")
object MyError2 : MyError("error 2")

val liveData:LiveData<Try<Result>> = MutableLiveData()

liveData.observe(..., Observer{ _try ->
    handlingSample(_try)
})

fun handlingSample(src: Try<Result>) {
    val result: String = src.fold(
            { error ->
                when (error) {
                    is MyError1 -> error.msg
                    is MyError2 -> error.msg
                    else -> "unknown error"
                }
            },
            { res ->
                "success"
            }
    )
}

fun aSometimeThrow():A
fun bSometimeThrow():B
fun cSometimeThrow():C
fun aTry():Try<A> = Try{ aSometimeThrow() }
fun bTry():Try<B> = Try{ bSometimeThrow() }
fun cTry():Try<C> = Try{ cSometimeThrow() }

fun kotlinSample() {
    try {
        val a = aSometimeThrow()
        val b = bSometimeThrow()
        val c = cSometimeThrow()
        nonErrorMethod(a, b, c)
    } catch (e:MyError) {
        // ...
    } catch (e:Throwable) {
        // ...
    }
}

fun useArrowSample() {

    val result1:Try<Result> = aTry().flatMap { a ->
        bTry().flatMap { b ->
            cTry().map { c ->
                nonErrorMethod(a, b, c)
            }
        }
    }

    val result2: Try<Result> = Try.monad().binding {
        val a = aTry().bind()
        val b = bTry().bind()
        val c = cTry().bind()
        nonErrorMethod(a, b, c)
    }.fix()

    val result3: Try<Result> =
            Try.applicative().map(aTry(), bTry(), cTry()) { (a, b, c) -> nonErrorMethod(a, b, c) }.fix()
            
    // call handlineSample etc...        
}

```

なんていうかびっくりするくらいOption版のコピペですね！

### reference

Tryに関しては結構色々なHandling方法や、Eitherへの変換とかあるので見ておいて損ないです
`Either<Throwable,...>`に便利メソッド生やしたって読み替えても良いと思います(雑)

https://arrow-kt.io/docs/datatypes/try/


# 中間まとめ

## ところどころドキュメント古い

正直この記事書く意味有るのかわからないくらい、公式Document充実しています。
が、注意する場所も…

Kotlin Slackの#arrowで
[we're deprecating ForXX extensions in favor of generating the extension functions directly on the types](https://kotlinlang.slack.com/archives/C5UPMM0A0/p1533658414000125)
と言っていますので、

```kotlin
ForOption extensions {
    binding {
        ...
    }
}
```
を

```kotlin
Option.monad().binding {
    ...
}
```

とかと読み替えておく必要はありそうです。

## 他

Option/Either/Tryの利用例が似ているというか一緒ですよね。
ということは、実は大体他に用意されているやつもおんなじように使えるようになっています。

ただのInterfaceっぽいですよね。

実はそれがM的なあれに…みたいなこと書くとアチラコチラから刺されそうですが…
[ここの説明とか読むとなんか納得してもらえるんじゃないかな](https://arrow-kt.io/docs/patterns/monads/)

とはいえここ見ている人は多分英語辛い派閥でしょうから、
上のリンクの「サンプルコードだけをゆっくり読めば」なるほど感になるのでは？？


# 疲れたので雑にいくつか

## 途中Eitherとかで包んでないんだけどよしなに包んで欲しい

```kotlin
val res1 = Either.monadError<Throwable>().bindingCatch {
    val a = Either.right(1).bind()
    val b = throwError() // ここでLeftになって返る
    a + b
}.fix()

val res2 = Try.monadError().bindingCatch {
    val a = Try.just(1).bind()
    val b = throwError() // ここでFailureになって返る
    a + b
}.fix()
```

`monad().binding{...}` → `monadError().bindingCatch{...}`に置き換えるとあら不思議

ただし、何でもかんでもbindingCatchが呼べるわけじゃないので…
IDEの補完で気がつくと思いますのでそれで。

Eitherの場合、LeftがThrowableなものに限定されます

[ドキュメント的にはこのへん](https://arrow-kt.io/docs/patterns/monad_comprehensions/#error-propagation-in-comprehensions)

## rxjavaチックにThread切り替えたい

```kotlin
Single.just(...)
    .map(...)
    .observeOn(Schedulers...)
    ...
    .subscribeOn(AndroidSchedulers...)
    ...

```

的なやつ

[このへんとか](https://arrow-kt.io/docs/patterns/monad_comprehensions/#non-blocking-thread-jumps)
[このへん](https://arrow-kt.io/docs/effects/async/#continueon)

根本的にタダの非同期処理として使う場合での比較という点はお間違えなく。

ちなみにメソッドチェーンで繋がなくてもできます

```kotlin
val (res1, disposable1) = IO.async().run {
    bindingCancellable {
        continueOn(Unconfined)
        val a = IO.just(1).bind()
        val b = throwError()
        a + b
    }
}

res1.fix().attempt().unsafeRunSync().fold(
        {
        },
        {
            fail()
        }
)

val (res2, disposable2) = DeferredK.async().run {
    bindingCancellable {
        continueOn(Unconfined)
        val a = DeferredK.just(1).bind()
        val b = throwError()
        a + b
    }
}

res2.fix().unsafeRunAsync {
    it.fold(
            {
            },
            {
                fail()
            }
    )
}
```

こんな感じとか。
さっきのbindingCatchの更に上位版みたいな（？）やつでCancellableというのがあります。
こうすると、戻り値がTupleになって、戻り値の2個めがCancel用のものになっています。

書き方が色々とあるのは良いのか悪いのか…

上の例だと `disposable1()` とかでCancelされます

[このへんとか](https://arrow-kt.io/docs/patterns/monad_comprehensions/#cancellation-and-cleanup-of-resources)


## `List<Option<Int>>`みたいなのが、`Option<List<Int>>`にならないかな？

これ、SuccessOrFailureの記事でも`List<SuccessOrFailure<String>>`みたいなの出てきてて思い出しました。
`SuccessOrFailure<List<String>>`みたいにしたい！とかありそうな気がするんですけども…
(まあError複数ある場合の処理を期待しているときはあれだが)

最後にReturnされるものが`List<Option<Int>>`とかだったら中身精査しろよ感ありますが、
処理の途中で`Option<...>`だったらflatMapに食わせられるのに…とかそんな時用途でしょうか。

```kotlin
val src = listOf(1, 2, 3, 4)
val target:List<Option<Int>> = src.map { (it % 2 == 0).maybe { it } }

val actual:Option<List<Int>> = target.k().sequence(Option.applicative()).fix()

assertEquals(actual, None)

val target2:List<Try<Int>> = src.map {
    Try {
        if (it % 2 == 0) it
        else throw Exception("$it")
    }
}

val actual2:Try<List<Int>> = target2.k().sequence(Try.applicative()).fix()

actual2.fold(
        {
            assertTrue(it.message == "1")
        },
        {
            fail()
        })

```

上の例だとそもそも奇数フィルターしろや案件ですがそのへんはまあ…例なので…
`sequence`と`applicative`というワードを覚えておくと良いことあるかもしれません。

これ、公式Documentだとどこなんでしょう…
Traverseあたりにそのうち書かれるのかな？
https://arrow-kt.io/docs/typeclasses/traverse/#traverse


## もっと強力な使い方無いの？？

`Option<Either<X,Y>>`みたいなのをキレイに（ネスト無く）使いたい！
とかになってくると、
[OptionT](https://arrow-kt.io/docs/datatypes/optiont/)とか
[EitherT](https://arrow-kt.io/docs/datatypes/eithert/)とか知りたくなるかと思います。

あとAndroidで…という文脈では余り使う機会が想像できないけど、
意味がわかるとなるほど！！って思えるのが[ValidatedとEitherを切り替えるサンプル](https://arrow-kt.io/docs/datatypes/validated/#alternative-validation-strategies-to-validated-using-applicativeerror)かと思います。

このサンプルだと、FormのFieldの入力をラベル、アドレス両方まとめてチェックしますが、
多分Android（というかフロントというか）だと、入力フォームそのものに（入力した端から）Validationをかけて、そのまま最初のErrorだけ表示

で、そのValidation(たち)を通ったものだけが伝搬してくるようにするかと思うので…

なんかあえてこっちを(特にValidatedを)使うケースがぱっと想像つかないんですよね。（あくまでもAndroid脳だと？）
[なおこの辺がサンプルとしてあります。](https://github.com/dcampogiani/AndroidFunctionalValidation)

ただ、このサンプルから学べることはいっぱいあると思うのでおすすめです。

まあ入れたらフル機能使わなければならない！なんてルールは無いですし、
Option/Eitherあたりから始めて、良かったら他のも試してみればよいかと思います。

# 終わり

なんか間違っていたり、もっとここんとこ書いて欲しい！とかありましたら、雑にご連絡ください。
`.k()`とか`Kind<F,A>`とかの説明とかが喜ばれたりするんでしょうか？？？
気が向いたら書きます。