#1前回は関数の記述と適用の話だった。if式にはelse節が必須など、いくつかのルールを学んだ。今回からはデータ構造の話、今回はリスト。リストの基本操作と性質まずはリスト。定義の仕方や扱い方はざっくりと他の言語と変わらないように見える。GHCi内での定義にはletを使うとひっそりtipsが書かれてる。リストの連結は++でおこなう。文字列は文字のリストとして表現されるので、リスト関数は文字列に対して適用できる。リストの末尾に連結をおこなうのは何度もスキャンが必要となるため遅い。リストの先頭への追加はとても速い(スキャンしないから)。これをおこなう演算子が:。cons演算子とも呼ばれる。ここの例で'h'など文字(Cでいうところのchar相当)指定が出てる。前回の中身でアポストロフィは名前の一部に使えるというのがあったけど、この感じだと先頭には使えない(letter表現とかぶるため)のだろう。cons演算子(:)で第一引数になるのは連結対象リストの単一要素。++演算子では両方ともリストを渡す。Haskellでは[1,2,3]は単に1:2:3:[]の糖衣構文と。リストの要素へのアクセスは!!でおこなう。リストの端を超えた場所にアクセスすると例外が投げられる。リストの中に更にリストを入れられるけれど、違う型はダメ。リストの比較は辞書順でおこなわれる。最初に見つかった異なる要素の順序が大小を決定する。空でないリストは常に空リストよりも大きいとみなされる。リストAがリストBのスーパーセットである場合はリストAのほうが大きいとみなされる。その他のリスト操作としてhead/tail/last/initの紹介。空のリストに対してこれらの操作をすると例外を吐く。length関数で要素数を調べたり、null関数で空か否かを調べたりして空リストへの操作が発生しないように処理すると。take関数は要素数を指定して取り出す。0を指定して空リスト取り出しができる。リスト要素数より多い要素を取り出そうとするとリスト全体が返される。[]は空リストを返すだけで特に問題ない。maximumとminimum関数は想像通りの挙動。elemは要素とリストを受け取って、指定要素がリストに含まれるかを返すもの。中置関数として使うことが多いという説明がされてる。レンジ指定はまあまあ賢いよという話。[1..20]は自然数を刻んでくれるし、[a..z]は小文字アルファベットを列挙してくれる。[1.1..20.0]を試してみると[1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1,10.1,11.1,12.1,13.1,14.1,15.1,16.1,17.1,18.1,19.1,20.1]となったので、まあこんなもんかなと。2つ目の要素を指定するとその差分を刻みとしてほどよくやってくれると。試しに[1,3..]とすると噂の無限リストがさっくり作れた。思ったらすぐ後にそのまま無限リストの話が出てきた。cycle関数は指定リストを無限にリピートする。repeatは単一要素を受け取ってそれをひたすら繰り返す(yesコマンドぽい)。replicateは指定要素からなる指定長のリストを作るもの。10)は同じになるけど、内部の処理的にはどっちのほうが効率的なのだろう、というのが気になったりした。続けてリスト内包表記の話。Pythonなどでお馴染みという感じだけど、あるリストから要素列を取り出して指定の名前に束縛し、加工方法を記載する出力パートに投げ込んで結果リストを作っておしまい。要素列の取り出しと束縛をおこなうパートにカンマで続けて条件(述語とも呼ぶ)をつけ、元リストからの取り出しをフィルタできると。条件はカンマで区切っていくつも書けるので、複数条件指定のためにわざわざリスト作成を何重にもおこなう必要はない。複数のリストからの取り出しも構文的には条件と同様なんだけど、利用時をイメージするとイマイチ直感的ではなかった。取り出した要素の全組み合わせが結果リストに反映される(5要素のxと3要素のyなどを取り出すと15要素の結果リストができる)。慣れると便利な局面が多そう。lengthっぽい関数を独自定義するくだりはゴリ押しすぎて面白かった。全要素を1に射影してsum*1。リストから取り出したけど使わない値を変数名_に突っ込んで捨てるのはお馴染みのイディオム。試してみると複数のリストからの取り出しで全部同じ変数へ突っ込むこともできるんだけど、その場合実際に取り出せるのは最後に書いたものらしい。[10,100]][10,100,10,100,10,100]ふむ。どっかに仕様書いてあるだろうからそのうち調べそうなメモ。]は慣れるとサクサク読み書きできそうだけど、あまり複雑になりすぎると脳スタックがあふれそうな気もした。外枠から把握していくとルール付ければ破綻はしないか。思ったら、入れ子の内包表記は複数行で書いたほうが読みやすいよと注記されていた。誰かのコードを読むなかで慣れよう。C#+LINQやRxの文脈でも似たことをやるコードは見かけますが、たとえば極単純な配列長チェックに使う場合は確実に無駄ですね。特定条件でフィルタした結果の件数取得などでは合理的な可能性あります。おしまいリストについてはここまで。写経しつつメモを書きながら読み進めたところ、分量的にはあまり進まなかった。各関数の挙動を実際に試しつつなので、まあこんなものかなとも思う。確実に「おっけー!」という部分がまだほとんどないので、出てきたものを片っ端からメモ取る状態になってるのが辛いところ。この先改善していくと良いけれど、あまり改善しないようなら何かしら方法を考える必要がある。[1..])と叩いてみたけど、結果がかえってくる気配がなかったから^Cで止めた。いうことは出来ないんだなぁ。MacBookを4/10に注文、4/14出荷、届いたのは4/17だったので正確にはもうすぐ2ヶ月ですが。Dockerで簡単にGPU対応のTensorFlow入りコンテナを作る方法こんにちは。作品群を読んでいたら連休が終わりそうです。重くなるので読み込まないようにすればOK。資料を補足するシリーズです。途中でやったことや、参考情報を書いていきます。