Category Archives: Scala - Page 2

ScalaMatsuri 2017 に参加してきました(プロローグ)

ScalaMatsuri 2017 に参加してきました。そこで何かと刺激を受けましたので、この3年以上も放置しているブログにレポートを載せたいと思います。いろいろ書きたいことがあるので、何回かに分けようかと思っています。

先に一番言いたいことを言っておく

いつまでモチベーションが保てるかわからないので、先に一番言いたいことを言っておきます。それは「ScalaMatsuri 最高に楽しいから参加したことないなら来年こそ参加しなよ!」ということです。

私自身もそうなので、特に地方の人にこそ参加して欲しいと思います。何故ならば、私は今回ScalaMatsuriに参加して自分が如何に孤独だったのかということを自覚し、そして満たされたからです。片田舎において、自分の力を総動員できる機会がどれほどあるでしょうか? 様々な仕事のしがらみや、自分以外の技術者のレベルの関係で不完全燃焼な毎日を送ることが常態化している地方在住の技術者のみなさん! ScalaMatsuri はそんな自分の力を総動員してあまりある話題で盛り沢山です! ネット越しでよくお見かけする、あの人やこの人! やっぱり生で見てもすごいです! 私が井の中の蛙であることはわかっていました。それでも、打ちひしがれることなんてないです。むしろ、満たされます!

自分についてと何故参加したのか

私は、コップ本第1版の和書が出た頃にScalaに本格的に取り組み始めたので、2009年がスタートの年です。それまではSeasar Projectに熱を上げていました(関連プロジェクトも含め、コミッタをしていたわけではありませんが、Exampleかなにかのクレジットに私の名前が入ったのもあったと思います)。その熱が少し落ち着いて次に食指を伸ばしたのがScalaだったのです。

当時はWebアプリケーションフレームワークとしてLiftが取り沙汰されていましたが、私にはピンと来ませんでした。ですのでもっぱらCubbyやWicketと言ったJava用のWebアプリケーションフレームワークでScalaを使っていました。社内や個人で使うツールやサービスを作るのに使用する程度でフルタイムで使っていたかと言えばそうでもありませんでした。あ、JOGLでゲームも作りました。

その後Play2がリリースされ、業務でもScalaプロジェクトが走り、納品まで至ることもありました。ですが、依然として「100%Scalaバリバリ!」という状態には残念ながら(業務では)なりませんでした。

ですから、私自身も「超最高Scalaプロフェッショナル!ばっちこい!」ってぐらいのスキルには到底達することはできませんでした。しかし、決して消えることのない火がありました。それは「Scala愛」です。

Scala好きすぎます! 楽しいです! 超活用したいです! 業務でバリバリ!なんて状態なんかまってられません。自分から行くしかないのです!

ということで、30代最後のほとばしりで ScalaMatsuri に参加しました。

ScalaMatsuri 参加まで

ScalaMatsuri のサイト、ニュービーにはわかりづらすぎます! DoorKeeper とかかっぺにはわかりづらすぎます! 「Scalaをテーマとしたカンファレンス」ってアバウトすぎます! 主催が誰なのかもよくわかりません! これ、参加に会社の決済欲しい人、相当苦労するんじゃないかと思います。

ScalaMatsuri 2018 のサイトを作成する際はぜひ「ちょっと頭の固い上司に見せる前提で、そんでもって決済の判断材料にされる」という視点を入れていただけたらと思います。あと、支払い方法もPayPalだから会社の決済降りないという人もいたかもしれませんね。

 

 

ということで、肝心の中身のレポートは次回以降に書きます。

Scalaの開発環境について

いつもは IntelliJ IDEA + Scala プラグインで Scala の開発をしていますが、ファイルによってすごくもっさりするので、他の開発環境はどうだろうかと試してみました。

Read more »

Scala 2.10 からの型クラス2(Functorはどうする?)

前回の記事にコメントをいただいて、Functor とか Monad なんかの高階型はどうするのか改めて考えてみました。

結論から言うと Scala は関数リテラルで型パラメータとれないので、関数リテラルだけでなんとかしようというのは不可能っぽいです(いまんところの私の頭では)。

しかし、implicity 使ったり context-bound を使わなくてもなんとかなりそうです。ここまで来ると型クラスじゃねーだろっ。と言われるかもしれませんがアドホック多相にはなってると思います。

ということで、Functor をやってみます。Haskell だとこんな感じですね。

class Functor f where
    fmap :: (a -> b) -> f a -> f b

Scala だと

import language.higherKinds
 
trait Functor[A] {
  type F[_]
  def fmap[B](func: A => B): F[B]
}
trait FunctorFunctions {
  def fmap[A, B](func: A => B)(f: Functor[A]): m.F[B] = f.fmap(func)
}

Option 型に適用してみます。

trait FunctorInstance {
  implicit class OptionFunctor[A](option: Option[A]) extends Functor[A] {
    type F[_] = Option[_]
    def fmap[B](func: A => B): Option[B] = option.map(func)
  }
}

使い方。

val allInstances = new FunctorInstance with FunctorFunctions {}
import allInstances._
 
val maybeInt = Option(3)
val func: Int => Int = _ * 2
 
println(maybeInt.fmap(func))
println(fmap(func)(maybeInt))
 
// こんな風にも使えます
def doubleInt(f: Functor[Int]): f.F[Int] = f.fmap(func)
 
println(doubleInt(maybeInt))

def は撲滅できませんでしたが、context-bound が撲滅できるのが私個人としては嬉しいです。それにやっぱりコード量はこっちのほうが少ないし!

でも、この fmap、カリー化を用いた部分適用(という言い方でいい?)できない! ぎゃふん!

Scala 2.10 からの型クラス

Scala で型クラス使おうという人ならば一度は目を通したことがあるだろう「空飛ぶサンドイッチのパーツ」。

Scala での型クラスの実装方法といったらたいていこの記事に書いてあるような方式になるのではないでしょうか(というか、私がググった限りではこのパターンしか見つけられなかった)。

でもこの方式、context-bound 型パラメータ使うんですよね。これのせいで def が登場しちゃうし、カリー化ができない。空飛ぶサンドイッチのパーツ自身、関数リテラル使おうぜ! と言いながらこのせいで def 使っちゃう。悔しい。それから、もっと便利にしようということで Scalaz みたいに Ops とか入れちゃって、型クラス実現するのにめんどうなこと!

ということで、Scala 2.10 から入った implicit classes 使うと型クラス簡単ですぜっていうのが今回の話です。空飛ぶサンドイッチのパーツの Depth をやってみます。

まず型クラス。ジェネリクスはいりません。

trait Depth {
  val: depth: Int
}

// お好みで関数バージョンも作りましょう
trait DepthFunctions {
  val depth: Depth => Int = _.depth
}

そして型インスタンス。

trait DepthInstances {
  implicit class TreeDepth(tree: Tree) extends Depth {
    val depth: Int = tree match {
      case Empty()    => 0
      case Leaf(_)    => 1
      case Node(l, r) => 1 + math.max(l.depth, r.depth)
    }
  }
  implicit class ListDepth(list: List[Int]) extends Depth {
    val depth: Int = list match {
      case xs => xs.size
    }
  }
}

使い方。空飛ぶサンドイッチのパーツでは、def になっていた halfDepth もこれで晴れて関数リテラルに!

val allInstances = new DepthInstances 
  with DepthFunctions {}
import allInstances._
val halfDepth: Depth => Int = _.depth / 2
// ↓ 関数バージョンを使えばこんな書き方もできます。
// val halfDepth: Depth => Int = d => depth(d) / 2
halfDepth(List(1, 2, 3, 4))

簡単! やった!