読者です 読者をやめる 読者になる 読者になる

独学大学情報学部

主にScala、たまにHaskell、稀に数学

「Scalaに存在演算子を求めるのは間違っているだろうか」をLens/Prismで解いてみる

元の記事はこちらです。

Scalaに存在演算子を求めるのは間違っているだろうか - だいたいよくわからないブログ

TL眺めてたらがくぞさんが

ってpostしてて「あ!このデータ構造、Lensのサンプルで見たことあるやつだ!」 が再生されたので(?)、やってみました。

もちろんScalaでLensといえばMonocleだよね!!*1

前置き

その1

何も考えずに各case classに対してLensを定義してやってみます。

ちなみに、&<-?applyPrism^|->composeLens^<-?composePrismエイリアスメソッドです。

このsomemonocle.std.option#someで、Monocle標準で提供してるPrismです。 b.valueOption[A]なので、a.valueする為にOption[A] => Aが必要だったので使用しています。

結果は以下の通り。

scala> Example1.good
res0: Option[Int] = Some(1)

scala> Example1.bad
res1: Option[Int] = None

良さそうですね。

その2

some分冗長な気がしたので、_b_dをPrismにしてみます。

これでsomeがなくなった分短く書けるようになりました。 もちろん、同じ結果が得られます。

scala> Example2.good
res2: Option[Int] = Some(1)

scala> Example2.bad
res3: Option[Int] = None

まとめ

どちらにせよCoffeeScriptっぽく書けるわけでもなく、@xuwei-k さんの

「Scalaに存在演算子を求めるのは間違っているだろうか」の解答例 - scalaとか・・・

val x: Option[Int] = OptValue(edcba).wrap._value._fuga._hoge._bar._foo

みたいな感じでOptionを意識することなく繋げることは出来ませんでした。 とはいえ、macroもType Dynamicも使ってない*2ので、それなりにシンプルにかけてるはず...

もっと短くカッコよく書ける方法があれば教えて下さい!!

おまけ

コードの表現的に負けてしまった(?)ので、Lens/Prismを使ったメリットを挙げておくと

のようにgetだけでなくsetやmodifyもできるようになります。やったぜ!

*1:Scalazにもshapelessにもあります。

*2:Monocle側のGenLensはマクロでLens生成してますけどね