play2.0を実行

$export PATH=$PATH:/usr/local/play2.0
$play
こんなエラーが出るので
Unable to access jarfile /usr/local/play2.0/framework/sbt/sbt-launch.jar
https://gist.github.com/1390651にある内容でplayを更新。
$ vi /usr/local/play2.0/play

再度$play
::::::::::::::::::::::::::::::::::::::::::::::

:: UNRESOLVED DEPENDENCIES ::

::::::::::::::::::::::::::::::::::::::::::::::

:: play#console_2.9.1;2.0-SNAPSHOT: not found

::::::::::::::::::::::::::::::::::::::::::::::

今ここorz

playframework with scalaでjoda-time

を使おうとしたらこんなエラー

error while loading DateTime, Missing dependency 'class org.joda.convert.FromString',

ここに書いてあるけど
http://groups.google.com/group/play-framework/browse_thread/thread/b448295a3d096b22

http://sourceforge.net/projects/joda-convert/files/joda-convert/
からjoda-convert.jarをダウンロードして%PLAY_HOME%/frameworklibの下に保存すると動く。

Real World Haskell 第4章練 習問題 続き

4.1 asInt_fold マイナス対応

import Data.Char

asInt_fold :: String -> Int
asInt_fold ('-':xs) = -1 * asInt_fold(xs)
asInt_fold xs = foldl step 0 xs
  where step acc x = acc * 10 + (digitToInt x)

4.2 エラー処理
オーバーフローしたときの処理が悩んだけど、前回の結果と比べて値が小さくなった場合にオーバーフローとして処理するように実装。

import Data.Char

asInt_fold :: String -> Int
asInt_fold [] = error "asInt_fold required argument"
asInt_fold ('-':xs)
  | xs == ""   = error "asInt_fold not allwoed only sigin"
  | otherwise  = -1 * asInt_fold(xs)
asInt_fold xs = foldl step 0 xs
  where step acc x | isDigit x = let acc' = acc * 10 + (digitToInt x)
                                 in if acc'> acc
                                    then acc'
                                    else error "overfllow!"
                   | otherwise = error "as_Int_fold only allowed digit or sigin"

4.3 Either
case 〜 of ってかっこいい。

import Data.Char

type ErrorMessage = String
asInt_fold :: String -> Either ErrorMessage Int
asInt_fold [] = Left "asInt_fold required argument"
asInt_fold ('-':xs)
  | xs == ""   = Left "asInt_fold not allwoed only sigin"
  | otherwise  = case asInt_fold xs of
                   Right rs -> Right (-1 * rs)
                   Left rs -> Left rs
asInt_fold xs = foldl step (Right 0) xs
  where step (Right acc) x | isDigit x = let acc' = acc * 10 + (digitToInt x)
                                         in if acc'> acc then Right acc' else Left "overfllow!"
                           | otherwise = Left "as_Int_fold only allowed digit or sigin"
        step (Left acc) _ = Left acc

4.4 my concat

foldr_concat ::[[a]] -> [a]
foldr_concat (x:xs) = foldr step x xs
  where step xs x = x ++ xs

4.4 takeWhileの2パターンの実装

myTakeWhile :: (a -> Bool) -> [a] -> [a]
myTakeWhile p (x:xs) | p x       = x : myTakeWhile p xs
                     | otherwise = []

foldrTakeWhile :: (a -> Bool) -> [a] -> [a]
foldrTakeWhile p xs = foldr step [] xs
  where step x acc | p x = x : acc
                   | otherwise = []

4.6 groupByを畳み込みで実現

foldGroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
foldGroupBy p xs = foldl step [] xs
  where step [] x = [x] : []
        step acc x | p (head (last acc)) x = (init acc) ++ [((last acc) ++ [x])]
                   | otherwise = acc ++ [[x]]

うーん、力技だなぁ。。

4.7 各種関数を畳み込みで実現

myAny :: (a -> Bool) ->[a] -> Bool
myAny p xs = foldr step False xs
  where step x f | f         = f
                 | otherwise = p x

myWords :: String -> [String]
myWords xs = foldr step [] xs
  where step x ys@(y:tail) | elem x [' ', '\r', '\n'] = [] :ys
                           | otherwise                = (x : y) : tail
        step x [] = [[x]]

myUnlines :: [String] -> String
myUnlines xs = foldr step "" xs
  where step x acc = x ++ "\n" ++ acc

cycleはあきらめる。普通にやったらこんな感じ

myCycle :: [a] -> [a]
myCycle xs = xs ++ myCycle xs

foldrは有限回数のループ(?)だから無限リストをあらわすのには向いていない。
無理やりやればできないことは無いだろうけど。。

原帰納的

Real World Haskellによると、foldrを使って表現できる関数を原始帰納的というらしいです。
結構な数の関数が原始帰納的らしく、本ではfilterの例がありました。

久しぶりにscalaでやってみたらこんな感じ。

scala> List(1, 2, 3).foldRight(Nil: List[Int]){(x, xs) => if (x %2 == 0) xs else x::xs}
res29: List[Int] = List(1, 3)

(1 :: (3 :: Nil))

ちなみにfoldLeftだとListが逆になっちゃう。

scala> List(1, 2, 3).foldLeft(Nil: List[Int]){(xs, x) => if (x %2 == 0) xs else x::xs}
res31: List[Int] = List(3, 1)

(3 :: (1 :: Nil))

forでぐるぐる回す処理を書いたときはちゃんと関数脳使ってるか確認したほうがよさげ。。

以下適当に実験
List(1, 2, 3) ++ List(4, 5, 6)

scala> List(1, 2, 3).foldRight(List(4, 5, 6)){_ :: _}
res35: List[Int] = List(1, 2, 3, 4, 5, 6)

List(1, 2, 3) map { _ + 1}

scala> List(1, 2, 3).foldRight(Nil:List[Int]){(x, xs) => ( x + 1) :: xs }
res46: List[Int] = List(2, 3, 4)

foldLeftだけど。。
List(1, 2, 3) reverse

scala> List (1, 2, 3).foldLeft(Nil:List[Int]){(xs, x) => x::xs}
res5: List[Int] = List(3, 2, 1)

ちょっと強引だけど
List(1, 2, 3) contains(2)

scala> List(1, 2, 3).foldRight(false){(x, xs) => xs || (x == 2)}
res60: Boolean = true

もちろん性能悪いです。こんなのでも原始帰納的といえるのかなぁ。

cygwinでsbtするとUnable to access jarfile・・・

参考にさせていただいたブログ
http://d.hatena.ne.jp/todomasa/20100909/1284009806

リンク先のブログに書いてありますが、windowsのパスの形式で記述しないといけないらしいです。

 java -Xmx512M -jar C:\\program\\cygwin\\usr\\local\\bin\\sbt-launch.jar "$@"