53ningen.com

@gomi_ningen's Website

Scalaでストリームを実装する

scala では基本的に式は正格評価されます。 評価を遅らせたい場合は、サンク(thunk)と呼ばれる関数にしてあげることになります。 単純な例から見てみてみましょう。

scala> 1
res4: Int = 1

scala> def one = () => 1
one: () => Int

scala> one()
res6: Int = 1

このようにある A 型の値をサンクにしたい場合は () => A 型の関数にしてあげればよいです。 評価したくなったタイミングで関数にユニット () を渡してあげる形になります。

特に関数定義の際に引数の評価を遅らせたいことがあると思います。 以下のように数字を 2 倍する関数を定義できます。

scala> def twice(x: () => Int) = 2 * x()
twice: (x: () => Int)Int

scala> twice(() => 2)
res: Int = 4

この場合、呼び出し側と実装部分で () を付けるのが面倒なのですが、 x とだけ書けば良いように、便利な...

Read More

@tailrec で末尾再帰チェック

末尾再帰を意図した関数には @scala.annotaition.tailrec を付けるとコンパイル時にチェックがかかるようになることを知りました。 またこのアノテーションによって IntelliJ IDEA も末尾再帰になっていないときに警告を出してくれます。

たとえば階乗を計算する関数は次のように書いてあげればよさそうです。

def factorial(n: Int): Int = {
  @annotation.tailrec
  def go(n: Int, acc: Int): Int =
    if (n <= 0) acc
    else go(n-1, n*acc)

  go(n, 1)
}

もし末尾再帰になっていないときは次のような挙動になります。

scala> @tailrec
     | def f() = "hoge"
<console>:9: error: @tailrec annotated method contains no recursive calls
       def f() = "hoge"
``...
Read More

Haskell 基本構文のまとめ

すごいHaskell楽しく学ぼうの1〜5章の内容をまとめました。

Haskellとは何か

  • 純粋関数型プログラミング言語
    • 副作用を持たない.関数に出来ることは,何か計算をしてその結果を返すことだけ.
    • これにより関数は同じ引数である限り,必ず同じ値を返す参照透過性を持つ.
  • 遅延評価
    • 関数の結果が与えられた引数にだけ依存しているのでいつ計算するか気にする必要がなくなる.したがってHaskellではギリギリまで計算を引き延ばす.
  • 静的型付け言語
    • コンパイル時におかしいところが分かる
  • 型推論
    • a = 5 * 4 としたときaは明らかに数.こういったことをHaskell の型システムが判断してくれる.
  • エレガントで簡潔
    • 高度な概念をふんだんにつかっているらしい

1. Starting Out

GHC 対話モードで遊んでみる

とりあえず基本演算をやってみる

ghci> -- 四則演算
ghci> 1 + ( 2 * 3 ) / 4 - 5
-2.5
ghci> -- ブール代数
ghci> not...
Read More

Copyright © 53ningen.com