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

はわわーっ

はわわわわっ

scalaで部分適用とか

scala

とりあえず整数a, bを引数にとってaからbまでの和を求めるみたいなやつ。

def sum(a: Int, b: Int): Int = {
  def iter(i: Int, s: Int): Int = {
    if (i > b) s
    else iter(i+1, s+i)
  }
  iter(a, 0)
}

println(sum(1, 5))
15

これを関数fをとるようにして f(x) の和を求めるようにする。

def sum(f: Int => Int, a: Int, b: Int): Int = {
  def iter(i: Int, s: Int): Int = {
    if (i > b) s
    else iter(i+1, s+f(i))
  }
  iter(a, 0)
}

println(sum((x: Int) => x, 1, 5))
println(sum((x: Int) => x * x, 1, 5))
15
55

引数にある

(x: Int) => x
(x: Int) => x * x

の部分はラムダ式。

この sum を (Int, Int) => Int という型の関数にする。

def sum(f: Int => Int): (Int, Int) => Int = {
  def sumF(a: Int, b: Int): Int = {
    def iter(i: Int, s: Int): Int = {
      if (i > b) s
      else iter(i+1, s+f(i))
    }
    iter(a, 0)
  }
  sumF
}

def sum1 = sum((x: Int) => x)
def sum2 = sum((x: Int) => x * x)

println(sum1(1, 5))
println(sum2(1, 5))
println((sum((x: Int) => x))(1, 5))
15
55
15

これは書き換えると

def sum(f: Int => Int)(a: Int, b: Int): Int = {
  def iter(i: Int, s: Int): Int = {
    if (i > b) s
    else iter(i+1, s+f(i))
  }
  iter(a, 0)
}

def sum1 = sum((x: Int) => x) _
def sum2 = sum((x: Int) => x*x) _

println(sum1(1,5))
println(sum2(1,5))
println(sum((x: Int) => x)(1,5))
15
55
15

こうなる。
この場合は部分適用するときに

def sum1 = sum((x: Int) => x) _

みたいに最後に _ が必要みたい。

ちなみに同じようなのを haskell で書いたら

sum' :: (Int -> Int) -> Int -> Int -> Int
sum' f a b = iter a 0
  where
    iter i s
      | i > b = s
      | otherwise = iter (i+1) (s + f i)

sum1 = sum' (\x -> x)
sum2 = sum' (\x -> x * x)

main = do
  print $ sum1 1 5
  print $ sum2 1 5
  print $ sum' (\x -> x) 1 5

こんな感じだろうか。