Friday, 18 June 2010

Haskell

微妙に頭が重い。高血圧の症状らしいです。最近、ずーっとそんな感じなので、そんなものなんでしょう。

Haskell 微妙に硬い。予想通りに動いてくれない感じ。Term Rewriting 系(項書換え)の言語は、動作予測が難しいんだよ。

Haskell は、なんと無限列が扱えます。遅延評価系、関数の内側から評価していくのではなくて、外から評価していく(outer most evaluation) なので、たらいが一瞬で終るとか、そんな話が。(たらいだったか自信がないが)
 
  [1..]

とかすると、[1,2,3, と、延々表示されます。しかも、

  Prelude> take 20 [1..]
  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

とか出来る。これ、別に特別なことをやっているわけではなくて、

  inc n = n : inc (n + 1)
  take1 0 x   = []
  take1 n (x:xs) = x : take1 (n-1) xs

とかで簡単に作れます。

  *Main> take1 20 (inc 1)
  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

面白い。C とか Java だと、止まらないんだよね。もっとも、Haskell だって止まらない例はいくらでも書けるんですが。

カッコ忘れると、

  *Main> take1 20 inc 1

  <interactive>:1:9:
Couldn't match expected type `[a]'
    against inferred type `a1 -> [a1]'
In the second argument of `take1', namely `inc'
In the expression: take1 20 inc 1
In the definition of `it': it = take1 20 inc 1

とたんにわからんメッセージが。まぁ、慣れればなんとかなるんだろうけど。

  ap [] t = t
  ap (x:xs) t = x : ap xs t

  rev x = rev1 x []

  rev1 [] x = x
  rev1 (x:xs) y = rev1 xs (x:y)

とか書くと、とっても Prolog っぽい。型推論のある言語と、型無しの言語ってのは、実は、ほとんど同じ。Prolog だと、

  ap([],X,X).
  ap([H|X],Y,[H|Z]) :- ap(X,Y,Z).

  rev(X,Y) :- rev(X,[],Y).

  rev([],X,X) .
  rev([H|X],Y,Z) :- rev(X,[H|Y],Z).

そっくりだ。Prolog の方がappend と reverse の対称性が明示されている。

で、問題は、Monad だな。

  getLine >>= putStrLn

とかやるんですが、こいつをどうやって書くのかが良くわからん。

http://book.realworldhaskell.org/read/

ってのがあるので、やっぱり本読むか。

No comments: