tsucchi’s diary(元はてなダイアリー)

はてなダイアリー(d.hatena.ne.jp/tsucchi1022)から移行したものです

「ふつうの Haskell プログラミング」一人読書会(2日目)

「ふつうのHaskellプログラミング」という本を読んでいます。


ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門

さて、今日は2章の残りと演習問題をやってみました。

まずは head です。ここで実装するのは、標準入力をうけて、先頭10行だけ表示する、というサブセット版だそうです。

例によって、普通の Perl で書くとこんな感じでしょうか

#!/usr/bin/perl
use strict;
use warnings;

my $count = 0;
while( <> ) {
    last if ( $count++ >= 10 );
    print $_;
}

で、Haskell 風に書くとこうなりました

#!/usr/bin/perl
use strict;
use warnings;

sub first_n_lines {
    my ($n_lines, @lines) = @_;
    return join "", @lines[0 .. $n_lines-1];
}

print first_n_lines(10, <>);

Haskell では take をつかうのですが、Perl には無いので、ふつうに配列スライスで取り出しています。相変わらず、変数の代入が無い美しいコードですね (棒

続いて、tail です。こちらも末尾10行だけ表示するサブセット版です。で、ふつうに書こうと思ったら、結構難しいんだよな、コレ。普通に書いたやつもゴルフ用みたいなコードになってしまいました。。。

#!/usr/bin/perl
use strict;
use warnings;

my @lines = <>;
print @lines[ $#lines + 1 - 10 .. $#lines];

で、Haskell 風がこっち

#!/usr/bin/perl
use strict;
use warnings;

print last_n_lines(10, <>);

sub last_n_lines {
    my ($n_lines, @lines) = @_;
    return join '', take_last($n_lines, @lines);
}

sub take_last {
    my ($n_lines, @lines) = @_;
    return reverse ((reverse @lines)[0 .. $n_lines-1]);
}

なんかどっちも変ですね。。。

最後に、演習問題です。最初は標準入力から与えられたバイト数を数えます。
ふつうの Perl で書くとこんな感じでしょうか。(use bytes しといたほうがいいけど、まあいいや)

#!/usr/bin/perl
use strict;
use warnings;

my $bytes = 0;
while( <> ) {
    $bytes += length $_;
}
print "$bytes\n";

Haskell ふうに書くとこうなりました。

print length join('', <>), "\n";

最後の改行は、文字列連結(.)を使っちゃダメだぞ!(length に連結された文字列が渡っちゃってうまく行かない。)*1

もう一問は、入力の単語数を数えるコマンドだそうです。「単語」の定義は Haskell の words 関数とするそうです。

Perl で書くときはめんどいので、勝手に split /\s+/ にしちゃいました。

普通にかくとこんな感じです。

my $num_words = 0;
while ( <> ) {
    my @words = split /\s+/, $_;
    $num_words += scalar(@words);
}
print "$num_words\n";

Haskell ふうに書くとこうなりました。

print scalar( split(/\s+/, join('', <>) ) ), "\n";

感想とか

多分ゴルフはうまくなったと思いますが、この学習を通じて HaskellPerl もうまくなった気がしないです orz

Perl で書いてみよう」と思ったときに、2章の途中あたりから、先に「Haskellふう」の実装を書くようになってしまったので、むしろ激しく有毒な気がします。日常でやってしまわないか心配です。。。

あと、この本のサポートサイトが落ちてるのはたまたまなんですかね?ソースコードの使用について確認したいのだけど。。。

*1:これは Perl の場合の注意点であり、Haskell の場合は関係ありません