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:
Post a Comment