2015年5月31日日曜日

scala関数型デザイン&プログラミング P105

Exercise 6.5 mapを使ってdoubleを実装し直せ

val rng = new scala.util.Random

trait RNG{
def nextInt:(Int,RNG)
}

case class SimpleRNG(seed: Long) extends RNG {
 def nextInt:(Int,RNG) = {
   val newSeed =(seed * 0x5DEECE66DL+0xBL) & 0xFFFFFFFFFFFFL
   val nextRNG= SimpleRNG(newSeed)
   val n = (newSeed >>>16).toInt
    (n,nextRNG)
 }
}

def nonNegativeInt(rng: RNG): (Int, RNG) = {
  val (i, r) = rng.nextInt
  (if (i < 0) -(i + 1) else i, r)
}

type Rand[+A]=RNG=>(A,RNG)

def map [A,B](s:Rand[A])(f:A=>B):Rand[B]=
 rng=>{
 val (a,rng2) = s(rng)
  (f(a),rng2)
}

def _double(rng:RNG):Rand[Double] =
 map (nonNegativeInt)(_/(Int.MaxValue.toDouble+1))

val (a,rng2) = _double(rng)(rng)で確認

2015年5月30日土曜日

scala関数型デザイン&プログラミング P103

Exercise 6.4 ランダムな整数のリストを生成する関数を記述せよ。
解答によれば
def ints(count: Int)(rng: RNG): (List[Int], RNG) =
  if (count <= 0)
    (List(), rng)
  else {
    val (x, r1)  = rng.nextInt
    val (xs, r2) = ints(count - 1)(r1)
    (x :: xs, r2)
  }
以下rngは略して、トレースしてみると
ints(0)()=(List(),rng)
ints(1)()=(x::List(), )
ints(2)()=(x::x::List(),)
と続くことになるようだ。

2015年5月28日木曜日

scala関数型デザイン&プログラミング P93

Exersise 5.12 unfoldを使ってmap,take,takeWhile,zipWith,zipAllを実装せよ。zipAll関数ではどちらかのストリームに要素が残っている限り、評価を続ける必要がある。(ストリームが完全に評価されたかどうかを示すのにOptionを使用する)

 def map3[B](f:A=>B):Stream[B] =
unfold(this)( p=>p match {case Cons(a,as)=>Some(f(a()),as())
 case _ => None
   })
省略形にすると
 def map4[B](f:A=>B):Stream[B] =
   unfold(this) {case Cons(a,as)=>Some(f(a()),as())
                 case _ => None
}


def take2(n:Int):Stream[A]=
   unfold((this,n)) {
  case (Cons(a,as),n) if (n>0) => Some( (a(),(as(),n-1))   )
  case _ => None
}


def takeWhile4(p:A=>Boolean):Stream[A] =
  unfold(this) {
  case (Cons(a,as)) if (p(a())) => Some(a(),as())
  case _ => None
  }

def zipWith2[A](as:Stream[A],bs:Stream[A])(f:(A,A)=>A):Stream[A]=
  unfold(as,bs) {
  case (Cons(a,as),Cons(b,bs)) => Some(f(a(),b()),(as(),bs()))
  case (_,_)=>None
}


def zipAll[B](s2:Stream[B]):Stream[(Option[A],Option[B])] =
  unfold(this,s2) {
  case (Cons(a,as),Cons(b,bs)) => Some((Some(a()),Some(b())),(as(),bs()))
ここで、はたと止まってしまった。
 case(Empty,Cons(b,bs))=>Some、、、、のところがどうしてもうまくいかない。
解答のプログラムもコンパイルしてみたが、エラーが発生する。


2015年5月26日火曜日

scala関数型デザイン&プログラミング P93

Exercise 5.11 より汎用的なunfoldを記述せよ

解答をみるとf(z) matchとしている。柔軟な発想が必要なようだ。
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] =
  f(z) match {
    case Some((h,s)) => cons(h, unfold(s)(f))
    case None => empty
  }
これまで、でてきた生成関数に共通する部分をみると
 def 自分自身(引数1)=cons(h,自分自身(引数2))
となっているので、引数1から引数2への変換のためにfという関数を用意し、同時にそのfの関数でhも求めるようにしている。

Exercise 5.12 fibs、from、constant,onesをunfoldを使って実装する。
   def fibs4(n1:Int,n2:Int)=
   unfold((n1,n2))( ((nn1,nn2)) => Some( (nn1,(nn2,nn1+nn2) ) )  )
としたが、なぜかエラー 1引数の関数にせよ。そのためにcaseパターンを使うということか?
解答のとおり
def fibs3(n1:Int,n2:Int)=
   unfold((n1,n2))( p=>p match  {case  (nn1,nn2) => Some( (nn1,(nn2,nn1+nn2) ) )  }  )
とするとうまくいく。 1引数としてpをとり、その戻り値がp match  {case  (nn1,nn2) => Some( (nn1,(nn2,nn1+nn2) ) )  } ということになるんだろうか。回りくどい感じがすると思うのは私だけだろうか。
省略形が
def fibs3(n1:Int,n2:Int)=
   unfold((n1,n2)) {case  (nn1,nn2) => Some( (nn1,(nn2,nn1+nn2) ) )  }
だとか。
 これ以降はmatchは使わなくてもよいようだ。
   def from2(n:Int):Stream[Int]=     unfold(n)( n=>Some((n,n+1)) )
def constant2[A](a:A):Stream[A]= unfold(a)(a=>Some(  (a , a )   ) )
def ones:Stream[Int]=unfold(1)(i=>Some((i,i)))



scala関数型デザイン&プログラミング P92

Exercise 5.8 指定された値の無限ストリームconstant関数を記述せよ
  def constant[A](a:A):Stream[A] =cons(a,constant(a))
解答は、次のようになっていた。これより効率のいい方法ということのようだ。
def constant[A](a: A): Stream[A] = {
  lazy val tail: Stream[A] = Cons(() => a, () => tail)
  tail
}

Exercise 5.9 nではじまり、n+1,n+2、、と続く無限ストリームを生成する関数を記述せよ
  def from(n:Int):Stream[Int] = cons(n,from(n+1))

Exercise 5.10 フィボナッチ数列の無限ストリームを生成するfibs関数を記述せよ
def fibs(n1:Int,n2:Int):Stream[Int]=cons(n1,cons(n2,fibs(n1+n2,n1+2*n2)))
解答は
val fibs = {
  def go(f0: Int, f1: Int): Stream[Int] =
    cons(f0, go(f1, f0+f1))
  go(0, 1)
}
これを見て
def fibs2(n1:Int,n2:Int):Stream[Int]=cons(n1,fibs2(n2,n1+n2))
でもいいのではないかと思ったが。。。

2015年5月25日月曜日

scala関数型デザイン&プログラミング P88 89

Exercise 5.4 Streamの要素のうち、指定された述語とマッチするものをすべてチェックするforAllを実装せよ。
def forAll(p:A=>Boolean):Boolean =
 foldRight(true)((a,b)=p(a)&&b)


Exercise 5.5 foldRightを使ってtakeWhileを実装せよ
 def takeWhile3(p:A=>Boolean):Stream[A] =
  foldRight(empty[A])((a,st)=>if p(a) cons(a,st) else st)
最後をstにしたが、解答はemptyだった。そうしないと、いったんfalseになっても、trueになると
前のStreamに追加されていく。(あとで出てくるfilterだとそれでいいが)

Exercise 5.6 foldRigthを使ってheadOptionを実装せよ
  def headOption:Option[A] =
 foldRight2(None:Option[A])( (a,_) =>if (a!=Nil) Some(a) else None )
最初foldRightの引数のNoneにOption[A]をつけなかったところ、エラーがでた。このへんの必要性について、いまいち理解できてない。
解答は
def headOption: Option[A] =
  foldRight(None: Option[A])((h,_) => Some(h))
となっていた。わざわざifはつける必要がないといことだ。hがNilでもNoneとなるようだ。

Exercise 5.7 foldRightを使って、map,filter,append.flatMapを実装せよ

def map[B](f:A=>B):Stream[B] =
 foldRight2(empty[B])( (a,st) => cons(f(a),st)  )

def filter(f: A => Boolean): Stream[A] =
 foldRight2(empty[B])( (a,st) => if (f(a)) cons(a,st) else st)

def append[A](as:Stream[A],bs:Stream[A]):Stream[A]=
 as.foldRight2(bs)((a,b)=>cons(a,b))
としたが、これでは引数を非正格にという条件にあわないので、間違い。
正しくは
 def append[B>:A] (bs: => Stream[B]):Stream[B]=
 foldRight2(bs)((a,b)=>cons(a,b))
ということだった。変位についても考慮して上位のBの型にしないとだめだそうだ。変位の指定ははまだ理解が難しい。

def flatMap[B](f:A=>Stream[B]):Stream[B] =
 foldRight(empty[B])( (a,st)=>cons(f(a).head,st)  ) 
ということは無理だったheadのような使いかたはできない
正解は  foldRight(empty[B])((a,st) => f(a).append(st))
appendを使うことは気づかなかった


2015年5月24日日曜日

scala関数型デザイン&プログラミング P86~87

Exercise5.2 Streamの先頭からn個の要素を取り出す関数take(n)とn個の要素をスキップするdrop(n)関数を実装せよ

 def take(n:Int):Stream[A] = this match {
    case Cons(x,xs) if n>1 => cons(x(),xs().take(n-1))
    case Cons(x,_) if n==1 => cons(x(),empty)
    case Empty => Stream()
}
これをprintln(Stream(1,2,3,4).take(2).toList)で確認してみた

  def drop(n:Int):Stream[A]=this match {
  case Cons(x,xs) if n>0 => xs().drop(n-1)
  case Cons(x,xs) if n==0 => cons(x(),xs())
  case Empty => Stream()
  }
println(Stream(1,2,3,4).drop(3).toList)で確認したが、これだと、無駄があったようだ。
def drop2(n: Int): Stream[A] = this match {
  case Cons(_, t) if n > 0 => t().drop(n - 1)
  case _ => this
}
解答はこうなっていた。

Exercise5.3 Streamの先頭から指定された述語とマッチする要素をすべて取り出す takeWhile関数を記述せよ
def takeWhile(f: A => Boolean): Stream[A] = this match {
  case Cons(h,t) if f(h()) => cons(h(), t() takeWhile f)
  case _ => empty
}
これは、なぜかprintln(Stream(1,2,3,4).takeWhile2(_>2).toList)とするとList()と表示される。
よく考えたら、先頭から~マッチしないとだめなわけだから、_>2でなく_<3などで試せばいいわけだ。

scala関数型デザイン&プログラミング P86

Exercise 5.1 StreamをListに変換し、それによりストリームを強制的に評価する関数を記述せよ。
なぜか、REPLではうまくいかなかった。eclipseでこんな感じで確かめてみた。末尾再帰でないので、あまりよくないらしい。解答にはよりよい方法がのっていた。

import Stream._
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]

object Main {
   def main(args:Array[String]) = {
println(Stream(1,2,3).toList)

trait Stream[+A] {
  def toList: List[A] = this match {
    case Empty => List()
    case Cons(h,t) => h() :: t().toList

  }
}

object Stream {
  def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
    lazy val head = hd
    lazy val tail = tl
    Cons(() => head, () => tail)
  }

  def empty[A]: Stream[A] = Empty

  def apply[A](as: A*): Stream[A] =
    if (as.isEmpty) empty
    else cons(as.head, apply(as.tail: _*))
}

こちらが模範解答だが、なかなか思いつかないかも
def toList: List[A] = {
  def go(s: Stream[A], acc: List[A]): List[A] = s match {
    case Cons(h,t) => go(t(), h() :: acc)
    case _ => acc
  }
  go(this, List()).reverse
}

scala関数型デザイン&プログラミング P77

Exercise 4.7 Eitherでsequenceとtraverseを実装せよ

 def sequence[E,A](es:List[Either[E,A]]):Either[E,List[A]]=
es match {
case Nil => Right(Nil)
case x::xs => x flatMap(xx => sequence(xs) map(xx::_) )
}
def traverse[E,A,B](as:List[A])(f:A=>Either[E,B]):Either[E,List[B]] =
 as match {
   case Nil => Right(Nil)
   case h::t => f(h).map2(traverse(t)(f))(_::_)
}
としてみた。
解答には
def sequence_1[E,A](es: List[Either[E,A]]): Either[E,List[A]] =
  traverse(es)(x => x)
のように、sequenceはtraverseを使う方法がでていた。

ただ、使い方がいまひとつわからなかった。
      val ls=List(Right(1),Right(2))
      val l=List(1,2)
      val el=Right(List(3,4))
      println(el.traverse(l)(i=>Right(i*2)))
      println(el.sequence(ls))
      println(el.sequence_1(ls))
  のように、elをつけないと実行できない。実際にはlやlsしか使ってないのだが。。。基本的なことなんだろうが、勉強不足。

scala関数型デザイン&プログラミング P76

Exercise 4.6 Right値を操作するmap,flatMap,orElse,map2をEitherに追加せよ

map2については内包表記を使うと簡潔になる

import scala.{Option => _, Either => _, _}


object Main {
    def main(args:Array[String]) = {
       val x=Right(1)
       val y=Left(22)
      println( x.map(i=>i*2))
      println(x.flatMap(i=>Right(i)))
      println(x.orElse(Left(999)))
      println(y.orElse(Left(999)))
      println(x.map2(Right(2))((a,b)=>a+b))
    }

}

sealed trait Either[+E,+A] {

  def map[B](f:A=>B):Either[E,B] = this match {
case Left(e) => Left(e)
case Right(a) => Right(f(a))
}


   def flatMap[EE>:E,B](f:A=>Either[EE,B]):Either[EE,B] = this match {
     case Left(e) => Left(e)
     case Right(a) => f(a)
   }

 def orElse[EE >: E, AA >: A](b: => Either[EE, AA]): Either[EE, AA] = this match {
   case Left(e) => b
  case a => a
 }

def map2[EE>:E,B,C](b:Either[EE,B])(f:(A,B)=>C):Either[EE,C] =
  for { a <- this; b1 <- b } yield f(a,b1)


}

case class Left[+E](get: E) extends Either[E,Nothing]
case class Right[+A](get: A) extends Either[Nothing,A]

2015年5月23日土曜日

scala関数型デザイン&プログラミング P73

Exercise4.5 traverse関数を実装せよ。リストを1回だけ調べる効率よい実装にすること。traverseの観点からsequenceを実装するとよい。

f(x):Option[B]だし、traverse()():Option[List[B]]なので
 x::xsから 最終的に map2(f(x),traverse(xs)(f))(_::_) にすればよさそうな気がしてた。
が、foldMapの使用も考えたりするうち、よくわからなくなり、正解を見た。
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] =
  a match {
    case Nil => Some(Nil)
    case h::t => map2(f(h), traverse(t)(f))(_ :: _)
  }

別解は
def traverse_1[A,B](a:List[A])(f:A=>Option[B]):Option[List[B]]  =
 a.foldRight[Option[List[B]] ](Some(Nil))( (x,y) => map2(f(x),y)(_::_) )

scala関数型デザイン&プログラミング Exercise 4.4

Exercise 4.4 OptionのリストをひとつのOptionにまとめるsequence関数を実装せよ。
def sequence[A](a:List[Option[A]]) :Option[List[A]] =
 a match {
 case Nil=>Some(Nil)
 case Some(x)::xs => Some( x::sequence(xs) )
}
と思ったが、sequence(xs)はList[A]でないから、当然エラーが発生する。Optionを取り除くという発想ではだめということがわかる。やはり、これまで通り、flatMapやmapを駆使するとうまくいくようだ。

正解は
def sequence[A](a:List[Option[A]]) :Option[List[A]] =
 a match {
 case Nil=>Some(Nil)
 case x::xs =>  x flatMap( xx => sequence(xs) map(xx::_) )
}
aはOption[A]のリストで、先頭をx、残りがxsとすると
xをflatMapに適用(関数は xx => sequence(xs) map(xx::_)  )
ここで、sequence(xs) map(xx::_) がなかなか発想できなかった。
Optin[List[A]]でなければならないので、Some(xx::(xsのOptionがとれたリスト))となるようにする必要がある
map((xsのOptionがとれたリスト)=>xx::(xsのOptionがとれたリスト))となるようにして、このmapは、何に適用なるかというと
sequence(xs)、つまり(xsのOptionがとれたリスト)のOptionということになる。

別解として、
def sequence_1[A](a: List[Option[A]]): Option[List[A]] =
  a.foldRight[Option[List[A]]](Some(Nil))( (x,y) => map2(x,y)(_ :: _) )
ここで、理由はまだよく理解してないが、[Option[List[A]]]がないとエラーになるようだ。

scala関数型デザイン&プログラミング Exercise 4.3

Exercise 4.32項関数を使いOption型の2つの値を結合する総称関数map2を実装せよ
def map2[A,B,C](a:Option[A],b:Option[B])(f:(A,B)=>C):Option[C] =
 (a,b) match {
  case (Some(aa),Some(bb)) => Some(f(aa,bb))
  case (_,_) =>None
}
と考えたが、Optionは原則flatMapを使ったほうがスマートになるらしい。解答は
def map2a[A,B,C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
  a flatMap (aa => b map (bb => f(aa, bb)))

def lift[A,B](f:A=>B):Option[A]=>Option[B]=_ map f
を参考にすると
 b map (bb => f(aa,bb))がいわゆるliftを適用したものにあたり bb=>f(aa,bb)がA=>Bにあたる。
Option[B]=>Option[C]という関数にbを適用した結果だから、b map (bb => f(aa,bb)):Option[C]とみなせる。
(ただ、この部分でaaが確定してないから、aaの関数ともみなせる?)
したがって、aa:AからOption[C]への関数がflatMapの引数となっており、
a:Option[A]をmap2aに適用すれば、Option[C]に変換される。
二項関数は、flatMapとmapをうまく組み合わせるとできるということは、わかったが、けっこう、ややこしい。

2015年5月21日木曜日

scala関数型デザイン&プログラミング P68

Exercise 4.2 flatMapをベースにしてvariance関数を実装せよ。math.pow(x-m,2)の平均が分散
def mean(xs:Seq[Double]):Option[Double]=
 if (xs.isEmpty) None
 else Some(xs.sum/xs.length)
を使うようだ。

meanのことを忘れていたし、まったく思いつかなかったので、正解を見たら
    def variance(xs:Seq[Double]):Option[Double]=
 mean(xs).flatMap(m=>mean(xs.map( x=>math.pow(x-m,2))))
となっている。たったこれだけの文字数ですむとは驚きだ。ためしに
def variance(xs:Seq[Double]):Option[Double]=
 mean(xs).flatMap(m=>mean(map(xs)(x=>math.pow(x-m,2))))
とすると、うまくいかなかった。Listのmapの仕様とはちがっている?ようだ。

scala関数型デザイン&プログラミング P67

Exercise4.1 trait Optionのmap,flatMap,getOeElse,getElse,filterの関数をOptionで実装せよ。

eclipseでコンパイルしないとうまく実行できなかった。
とりあえず、解答も参考にしながら、次のようなものを考えてみた。

import scala.{Option => _, Either => _, _}

//以下のprintln文で動作を確認してみた
object Main {
   def main(args:Array[String]) = {

       val x:Option[Int]=Some(1)
       val y:Option[String]=None
       println(x)
       println(x.map(i=>i.toDouble))
       println(y.getOrElse(999))
       println(x.flatMap(i=>Some(i.toDouble)))
       println(x.filter(_<2))

    }
}


case class Some[+A](get: A) extends Option[A]
case object None extends Option[Nothing]

sealed trait Option[+A] {
  def map[B](f: A => B): Option[B] = this match {
    case None => None
    case Some(a) => Some(f(a))
  }


//Option値がNoneなら、ディフォルト値だが、Someならその中身
// 引数名: =>引数の型  は、遅延評価(メソッド呼び出す前には評価されない)
  def getOrElse[B>:A](default: => B): B = this match {
   case None => default
   case Some(a) => a
   }
 

  def flatMap[B](f: A => Option[B]): Option[B] =
    map(f).getOrElse(None)

 //二つ目のOptionというのが意味が分からなかったが、要するに引数のことでしょうか?
 //orElse(一つ目のOption,二つ目のOption)とみなしたということ? 一つ目のOption.orElse(二つ目のOption)と考えていたのでよくわからなかった。
 //自分自身はthisとするようだ
    def orElse[B>:A](ob: => Option[B]): Option[B] = this match {
    case None=> ob
    case Some(b) => this
    }
// 解答の
//  def orElse[B>:A](ob: => Option[B]): Option[B] =
//    this map (Some(_)) getOrElse ob
//  という発想はなかなか出てこなかった。Some(_)は、b:B=>Some(b):Option[B] そして
//map(b=>Some(b)でSome(Some(b))になるが
  //getOrElseでまた、Some(b)にもどるということだろうか。ちょっと回りくどい気がしないでもないが。

    def filter(f: A => Boolean): Option[A] = this match {
    case None => None
    case Some(a) => if (f(a)) this else None
    }
}

2015年5月17日日曜日

scala関数型デザイン&プログラミング P57

Exercise 3.29 size,maximum,depth,mapを一般化し、それらの類似点を抽象化する新しいfold関数を記述せよ。
def fold[A,B](t:Tree[A])(lf:A=>B,bf:(B,B)=>B):B=
 t match {
   case Leaf(a) =>lf(a)
   case Branch(lt,rt)=>bf(fold(lt)(lf,bf),fold(rt)(lf,bf))
 }
 size,maximum,depth,mapの類似点は、
1)t:Tree[A]が引数で、match式で使われていること
2)case Leaf(a)の右側がaの関数と考えられる
 このaの関数lfがいろいろ変えることで、一般化できる。このlfをfoldの引数にしてやるとよい。
3)case Branch(lt,rt)の右側がlt,rtを引数とした再帰関数の関数と考えられる
 このlt,rtを引数とした再帰関数は、どれにも共通しているので、これらfold(lt)(lf,bf)とfold(rt)(lf,bf)を引数としたbfという関数をいろいろ変えることで、一般化できる。それで、このbfもfoldの引数にする。

関数を引数にできると、プログラムの抽象化の幅も広がるということがこの練習問題からよくわかります。

scala関数型デザイン&プログラミング P56

 Exercise 3.25 LeafとBranchの数を数えるsize関数を記述せよ
 def size[A](t:Tree[A]):Int=
  t match {
  case Leaf(a) => 1
  case Branch(lt,rt) => 1+size(lt)+size(rt)
  }

Exercise 3.26 Tree[Int]の最大の要素を]返すmaximum関数を記述せよ。
def maximum(t:Tree[Int]):Int=
 t match {
  case Leaf(a) =>a
  case Branch(lt,rt) => maximum(lt) max maximum(rt)
 }

 Exercise 3.27 2分木のルートから任意のLeafまでの最長パスを返すdepth関数を記述せよ
 def depth[A](t:Tree[A]):Int=
  t match {
   case Leaf(_) => 0
   case Branch(lt,rt) => 1+(depth(lt) max depth(rt))
  }

  Exercise 3.28 2分木の各要素を特定の関数を使って変換するmap関数を記述せよ。
def map[A,B](t:Tree[A])(f:A=>B):Tree[B]=
 t match {
  case Leaf(a)=>Leaf(f(a))
  case Branch(lt,rt)=>Branch(map(lt)(f),map(rt)(f))
 }

scala関数デザイン&プログラミング P54


Exercise 3.24 Listに別のListがサブシーケンスとして含まれるかどうか調べるhasSubsequenceを実装せよ
def hasSubsequence[A](sup:List[A],sub:List[A]):Boolean =
  (sup,sub) match {
  case (Nil,_) => false
  case (_,Nil) => true
  case (Cons(x,xs),Cons(y,ys)) => if (x==y) hasSubsequence(xs,ys) else hasSubsequence(xs,sub)
  }
としてみたが、間違いに気づいた。最初に、  case (_,Nil) => trueをもってこないと、うまくいかない。
def hasSubsequence[A](sup:List[A],sub:List[A]):Boolean =
  (sup,sub) match {
  case (_,Nil) => true
  case (Nil,_) => false
  case (Cons(x,xs),Cons(y,ys)) => if (x==y) hasSubsequence(xs,ys) else hasSubsequence(xs,sub)
  }
これでも、まだ完全ではない。途中までx==yだと、ysに半端なListが行くため、もともとのsubにリセットされない。
そこで、次のようにしてみた。
def hasSubsequence[A](sup:List[A],sub:List[A]):Boolean =
{
 def icchi(supx:List[A],subx:List[A]):Boolean =
  (supx,subx) match {
   case (_,Nil) => true
  case (Nil,_) => false
  case (Cons(x,xs),Cons(y,ys)) => if (x==y) icchi(xs,ys) else icchi(xs,sub)
  }
 icchi(sup,sub)
 }
あまりすっきりした形ではないが、これでどうだろうか?意外に難しい。

scala関数デザイン&プログラミング P53

Exercise3.20 mapと同じ働きをするflatMap関数を記述せよ。
def flatMap[A,B](as:List[A])(f:A=>List[B]):List[B] =
 foldRight(as:List[A],Nil:List[B])( (x,bs)=>concat(List(f(x),bs))  )

 もっと簡単に
 def flatMap[A,B](l: List[A])(f: A => List[B]): List[B] =
  concat(map(l)(f))
  でいいようだ。map(l)(f)はList(List[B])の型になるが、concatによりList[B]になるということのようだ。


Exercise3.21 flatMapを使ってfilterを実装せよ。
 def filter2[A](as:List[A])(f:A=>Boolean):List[A]=
  flatMap(as)((i)=> if (f(i)) List(i) else List() )

Exercise3.22 リスト2つをうけとり、対応する要素どうしを足し合わせて新しいリストを生成する関数を記述せよ
 def plus(as:List[Int],bs:List[Int]):List[Int]=
  (as,bs) match {
   case (Nil,Nil)=>Nil
   case (Cons(x,xs),Nil)=>Cons(x,plus(xs,Nil))
   case (Nil,Cons(y,ys))=>Cons(y,plus(Nil,ys))
   case (Cons(x,xs),Cons(y,ys)) => Cons(x+y,plus(xs,ys))
   }
解答は、どちらも数字がないと足さないとしていたが、ここでは、数字がないときは、0とみなしていちおう計算してみた。

Exercise3.23 3.22で作成した関数を、整数または加算に限定されないように一般化せよ
def zipWith[A](as:List[A],bs:List[A])(f:(A,A)=>A):List[A]=
 (as,bs) match {
   case (_,Nil)=>Nil
   case (Nil,_)=>Nil
   case (Cons(x,xs),Cons(y,ys)) => Cons(f(x,y),zipWith(xs,ys)(f))
   }
正解では、すべての型をAにしていなかった。f:(A,B)=>Cと直す必要あり。

scala関数デザイン&プログラミング P52

Exercise 3.16 各要素に1ずつたして整数のリストを返す関数を記述せよ

def add1(as:List[Int]):List[Int]=
 as match {
  case Nil => Nil
  case Cons(x,xs)=> Cons(x+1,add1(xs))
}

def add1f(as:List[Int]):List[Int]=
  foldRight(as:List[Int],Nil:List[Int])((a:Int,b:List[Int])=>Cons(a+1,b))


Exercise 3.17 List[Double]の各値をStringに変換する関数を記述せよ

def toStringD(as:List[Double]):List[String]=
 foldRight(as:List[Double],Nil:List[String])((a:Double,b:List[String])=>Cons(a.toString,b))

Exercise 3.18 リストの各要素を変更し、かつリストの構造をそのまま保つ総称関数mapを記述せよ。
def map[A,B}(as:List[A])(f:A=>B):List[B]=
 foldRight(as:List[A],Nil:List[B])((a:A,b:List[B])=>Cons(f(a),b))

Exercise 3.19 与えられた述語条件が満たされるまでリストから要素を削除するfilter関数を記述せよ。

def filter[A](as:List[A])(f:A=>Boolean):List[A]=
 foldRight(as:List[A],Nil:List[A])((a:A,b:List[A])=>(if (f(a)) Cons(a,b) else b ))

scala関数型デザイン&プログラミング P51-2

Exercise 3.14 foledLeftまたはfoldRightをベースとしてappendを実装せよ。
def append[A](as:List[A],bs:List[A]):List[A]=
 foldLeft(reverse(as):List[A],bs:List[A])((b:List[A],a:A)=>Cons(a,b))

def append2[A](as:List[A],bs:List[A]):List[A]=
 foldRight(as:List[A],bs:List[A])((a:A,b:List[A])=>Cons(a,b))

foldRightのほうは、reverseが不要なのでシンプル

Exercise 3.15 複数のリストからなるリストを一つのリストとして連結する関数を記述せよ。
実行時間についてはよくわからないが、これでどうか?
def renketu[A](as:List[List[A]]):List[A]=
 foldRight(as:List[List[A]],Nil:List[A])((a:List[A],b:List[A])=>append(a,b))

2015年5月16日土曜日

scala関数型デザイン&プログラミング P51

Exercise3.11 foldLeftを使ってsum,product、リストの長さを計算する関数を記述せよ

def sum2(as:List[Int]):Int=
 foldLeft(as,0)(_+_)

def product2(as:List[Int]):Int=
 foldLeft(as,1)(_*_)

def length2[A](as:List[A]):Int=
 foldLeft(as,0)((b,_)=>b+1)

Exercise3.12 要素が逆に並んだリストを返す関数を記述せよ。
def rev[A](as:List[A]):List[A]=
 foldLeft(as,Nil:List[A])((b,a)=>Cons(a,b))

Exercise3.13 foldRigtからfoldLeftをつくる
def foldLeft2[A,B](as:List[A],z:B)(f:(B,A)=>B):B=
 {
 def g(a:A,b:B) :B =  f(b,a)
 foldRight(as,z)(g)
 }

foldLeftからfoldRightをつくる
def foldRight2[A,B](as:List[A],z:B)(f:(A,B)=>B):B=
 {
 def g(b:B,a:A) :B =  f(a,b)
 foldLeft(as,z)(g)
 }
としてみたが、そう簡単ではなかった。

3.13のfoldLeft2の正解は、
def foldLeftViaFoldRight[A,B](l: List[A], z: B)(f: (B,A) => B): B =
  foldRight(l, (b:B) => b)((a,g) => b => g(f(b,a)))(z)
なのだが、これを見ても、すぐには理解できない。
  foldRightの第一引数の型、List[A]でいいが、第二引数の型が、BのかわりにB=>B、つまり値ではなく、関数(b:B)=>bとするという考え方が、なかなか思いつかないところ。確かに、よく考えれば、型Bといえば、値であろうと関数であろうと論理的に問題はないことになる。
 したがって、次の引数である(A,B)=>BのBのところが、関数B=>Bに変わるので、(A,B=>B)=>(B=>B)となる。これは、(a,g) =>( b=>g(f(b,a))  )の部分で、gもB=>Bという型だし、b=>g(f(b,a))もB=>Bという型になっているから、これも問題ない。
 このB=>Bという関数が、foldRightで適用されたものは、foldRight(l, (b:B) => b)((a,g) => b => g(f(b,a)))であるが、これは、Bという型でなく、最終的にB=>Bの関数になるので、これだけでは、値が出てこない。そこで、この最終的にできた関数にzを引数としてやると
 foldRight(l, (b:B) => b)((a,g) => b => g(f(b,a)))(z) となるようだ。

def foldRight(x:xs,z)(f)はf(x,foldRight(xs,z)(f))となっているが、このzの部分がdelay関数と呼ばれている?もののようだ。再帰を繰り返すことで、delay関数にxが適用なっていき、蓄積していくイメージだろうか。これをもとにして、次のようになる。
foldRight(1:List(2,3),b=>b)(f)=f(1,foldRight(List(2,3),b=>b)(f))=f(1,f(2,foldRight(List(3),b=>b)(f)))
=f(1,f(2,f(3,b=>b)))
  ここで、fは(a,g)=>(b=>g(f(b,a))) より  f(3,b=>b)=(Ident(f(b,3))
 同様に fは(a,g)=>(b=>g(f(b,a))) より  f(2,(f3,b=>b))=f(2,Ident(f(b,3)))=Ident(f(f(b,2),3))
 これを繰り返し f(1,(f(2,f(3,b=>b)))=Ident(f(f(f(b,1),2),3)))


scala関数型デザイン&プログラミング P50

Exercise3.9 foldRightを使ってリストの長さを計算せよ
def length[A](as:List[A]):Int=
 foldRight(as,0)((a,b)=>b+1)

Exercise3.10 リスト再帰の総称関数foldLeftを記述せよ。
def foldLeft[A,B](as:List[A],z:B)(f:(B,A)=>B):B =
 as match {
      case Nil => z
      case Cons(x, xs) =>      f(foldLeft(xs, z)(f),x)
    }
これで、求められるけれど、末尾再帰でないので、だめなようだ。
あくまで、最後はfoldLeftの形でないとだめなので、正しい答は
def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match {
  case Nil => z
  case Cons(x,xs) => foldLeft(xs, f(z,x))(f)
}

2015年5月14日木曜日

scala関数型デザイン&プログラミング P45

Exercise 3.4  tailを一般化して、リストの先頭からn個の要素を削除するdropという関数に書き換えよ。
  def drop[A](l:List[A],n:Int):List[A] =
   l match {
   case Nil=>Nil
   case Cons(x,xs)=>if (n>1) drop(xs,n-1)
                    else xs
   }


Exercise 3.5 述語とマッチする場合に限り、Listからその要素までの要素を削除するdropWhileを実装せよ。
   def dropWhile[A](l:List[A],f:A=>Boolean):List[A] =
    l match {
     case Nil=>Nil
     case Cons(x,xs)=>if (f(x)) dropWhile(xs,f)
                      else l
    }

としてみたが、どうだろうか。

2015年5月13日水曜日

scala関数型デザイン&プログラミング P44

Exercise3.2
 Listの最初の要素を削除する関数tailを実装せよ。

 def tail[A](as:List[A]):List[A]=
   as match {
     case Nil => Nil
     case Cons(x,xs)=>xs
}

Exercise3.3
 最初の要素を別の値と置き換えるsetHead関数を実装せよ。

def setHead[A] (as:List[A] , y:A ) : List[A] =
 as match {
   case Nil =>Nil
  case Cons(x,xs)=>Cons(y,xs)
}

2015年5月12日火曜日

Scala関数型デザイン&プログラミング P34

Exercise2.3
カリー化では、引数2つの関数fが、fを部分的に適用する引数1つの関数に変換される。この場合も、コンパイルできる実装は1つだけである。この実装を記述せよ。
 def curry[A,B,C](f:(A,B)=>C):A=>(B=>C) =
   a=>(b=>f(a,b))  これは a=>b=>f(a,b)という書き方でいいのだろうか。

  curryの返り値としては、aを決めれば b=>cつまりb=>f(a,b)となる関数ができる と理解していいのだろうか。
 
Exercise2.4
Curryによる変換を逆向きに行うuncurryを実装せよ。=>は右結合であるため、A=>(B=>C)はA=>B=>Cと記述できる。
 def uncurry{A,B,C](f:A=>B=>C):(A,B)=>C =
    (a,b)=>f(a)(b)
fは、aを引数として、b=>cとなる関数を返す関数
b=>cという関数がf(a) つまり  bを引数としてf(a)という関数がf(a)(b)を返すという意味で
とらえるということと理解したが、これでいいのだろうか。

2015年5月4日月曜日

Raspberry Pi 2 sdrサーバとしても利用

 rtl_tcpを利用して、Sdrサーバ(FMラジオ等)としても、利用しようとしていたのですが、以前のraspberry Piのようにはうまくいきませんでした。いったん接続をやめると、2回目は接続できないという不具合は解消しませんでした。
 いろいろ調べたものの解決方法はけっこう難しそうです。そこで、応急処置的ですが、PHPを利用して、rtl_tcpをシェルスクリプトでリスタートさせる方法をとってみたところ、何とか実用になりました。
 PHPは、sdr#をロードしたときに、以下のように、呼び出すようにしてみました。

 private void MainForm_Load(object sender, EventArgs e)
        {
            Encoding enc = Encoding.GetEncoding("Shift_JIS");
            HttpWebRequest req    =HttpWebRequest)WebRequest.Create("http://hostname/sdron.php");
            WebResponse res = req.GetResponse();
            Stream st = res.GetResponseStream();
            StreamReader sr = new StreamReader(st, enc);
            string html = sr.ReadToEnd();
            sr.Close();
            st.Close();
       
        }


==sdr.sh== chmod +xで実行権限もたせる必要あり
#!/bin/sh
service rtl_tcp restart


==sdr.php==
<?php
exec("/home/pi/sdr.sh");
?>
==sdron.php==
<?php
exec("sudo php -f /var/www/sdr.php");
print_r("sdr recovery" );
?>

2015年5月2日土曜日

RasPi2 クアッド コアの威力

 SoftetherをRasPi2に入れてみた。Ipv6でつないだところ、トンネルの中のIPv4は、これまでの数倍速度アップしたようだ。
 ただ、以前行ったクロスコンパイルの方法やaufsの入れ方は、だいぶ忘れていて、けっこう時間がかかってしまった。それに加えて、rasPi2のsdカードの接触が悪いせいか、ときどき起動しなくなることがあった。カードを差し込み直すと解消するという状態なので、いまひとつ安定性が心配だ。

Java ダウンロード測度アップ

 自作のグループウエアこれまで、ファイルのダウンロードは特に、Servletを使わず、<a href=のリンクからそのままダウンロードするようにしていたが、どうも遅いときがあるので、気になっていた。
 試しに、Servletを使ってみたら、だいぶ早くなったような気がする。bufferの大きさもある程度大きくとってみた。以下を参考にさせていただいた。
  http://www.syboos.jp/java/doc/file-download-by-servlet.html
 ただ、問題は、全角のファイル名だと、ダウンロードがうまくいかない。いろいろ調べたら、けっこう面倒な対処が必要だと判明。以下のリンクで助けられました。
 http://eiryu.hatenablog.com/entry/20120708/1341735000