狠狠撸

狠狠撸Share a Scribd company logo
すごい配列楽しく学ぼう
     ~ Haskell の配列事情 ~
           @xenophobia__




?      ?
テーマについて
勉強会をやるらしい
→ 各 λ 人の好きな題材でいいらしい。
→ じゃあ Haskell で何か話そう。
→ でもすごい H 本出たし基本的なことはもう話題と
 して出尽してるよな……
→ あれ?この本配列について書いてなくね?
→?λ < Haskell の配列も楽しく学ぼう!



    ?        ?
Haskell とは!
   なんてことを話している時間はない。
   とりあえず今後の話に関わることとしてこれぐらい。
            型に厳しい(強い静的型付けである)
                  キャストとかゆとりな事はしない
                  型が合ってないと絶対許してくれない
            参照透明性が(基本的には)成り立つ
                  IO ?破壊的変更の扱いがめんどい特殊
                  unsafe ほげほげの話はしない
            「型クラス」がある
                  「型クラス」は共通の性質を持った型の集まり
                  ある型クラスに関して polymorphic な関数とか書ける
         ?              ?
Haskell の配列について
   Haskell では、コレクションは普通リスト型で扱う。
   配列はあんまり話題にならない気がする(すごい H
     本にも記述は多分ない? RHW にはあった)
   調べるといろいろ (Array,?UArray,?IArray,?MArray,?
     IOArray,?...) でてきてよくわからない。


   でも……
             プロコンとかだと使いたい。
             できるだけ速いほうがいい。
          ?         ?
Agenda
   とりあえず普通の配列( Array,?UArray )
   O(1) で変更できなきゃ配列じゃない! (IOArray,?
     IOUArray)
   型クラスの話をしよう (IArray,?MArray)




      ?         ?
Agenda
   とりあえず普通の配列( Array,?UArray )
   O(1) で変更できなきゃ配列じゃない! (IOArray,?
     IOUArray)
   型クラスの話をしよう (IArray,?MArray)




      ?         ?
Haskell 標準の配列を使う
   Array,?UArray (違いはあとで。)
   Array は Data.Array( または Data.Array.IArray) に
     ある。
   UArray は Data.Array.Unboxed にある。




       ?           ?
Haskell 標準の配列を使う
   配列を作るには?
    →?array 関数を使う(或いは listArray )
             array?(0,?3)?[(0,?1),?(1,?2),?(2,?4),?(3,?9)]
             array?((1,?1),?(2,?2))?[((1,1),?'a'),?((1,2),?'a'),?((2,1),?'z'),?
                ((2,2),?'d')]
             listArray?(1,?100)?[0,?0?..]
   インデックスには、 Int,?Char 及びそのタプルなどが
     使える。
                       厳密には Ix 型クラスのインスタンスがすべて使える。
                         ここでは説明は省略。
          ?                     ?
Haskell 標準の配列を使う
   型は?
   C などと違い、インデックスもいろいろ使える。
      → インデックスも型パラメタとして与える。
   インデックスが Int で要素が String の Array なら、
     Array?Int?String? となる。
   インデックスが (Char,?Char) で要素が Int の
     UArray なら、 UArray?(Char,?Char)?Int となる。



       ?           ?
Haskell 標準の配列を使う
   配列 ary の要素にアクセスしたい → (!) 演算子
             例) let?x?=?ary!2?in?…
              ???????let?x?=?ary!(0,?3)?in?…
   配列 ary の要素を更新したい → (//) 演算子
             例) let?ary'?=?ary//[(1,?2),?(3,?0)]
                     ???ary[1] を 2 に、 ary[3] を 0 に更新
             ただし、これには後に述べるように罠が隠れている。




          ?                   ?
Array/UArray の違いって?
   Array 型と UArray 型は、使い方はほぼ同じ。
   じゃあ違いは?
             Array は Box 化されている
             Uarray は Box 化されていない


   (? ? _ ? `) ? < おまえは なにを いってるんだ




          ?            ?
Array/UArray の違いって?
   つまり
            Array は、オブジェクトへのポインタを持った配列
            UArray は、値そのものを入れる配列
   もっと言うと
            Array は Lazy な配列
            UArray は Strict な配列




         ?              ?
Array/UArray の違いって?
   Array の要素を参照するときの動作
   ポインタが示す先に行き、オブジェクトを返す
               そのオブジェクトの値が必要になったら評価する。
               もちろん、オブジェクトが評価済みならその値自体を
                 返す。
    0

    1                     未評価              評価済み
                                    Eval
    2
                          10 * 10           100
    3




            ?         ?
なんでそんなことになってんの?
   知らん。




      ?    ?
なんでそんなことになってんの?
   …… ではさすがにあんまりなので。


   Array が正格評価する仕様だと、例えば変数 x,?y,?
     z を用いて
          ary?=?array?(1,?3)?[(1,?x),?(2,?y),?(3,?z)]
    のようにに配列を作ると、 x,?y,?z は配列作成時に
     全て評価されなければならない。(評価しないと
     格納する値がわからない)


      ?                   ?
なんでそんなことになってんの?
   「 x を配列に入れる」というロジックに「 x を評価す
      る」ことは必要か?
   たとえば ary のうち一つの要素にしかアクセスしな
     いかもしれない。
    → 「アクセスしない=使わない」ってことじゃない
     の?




      ?       ?
なんでそんなことになってんの?
   λ <使わないのに評価されるのは遅延評価とし
     ておかしい!( Haskell は call?by?need の遅延評
     価!)
   要素が何であるかの評価は、実際にその要素の値
     が必要になるまで遅延するのがよい!
               てな感じなんじゃないですかね。知らんけど……




       ?         ?
UArray(Unboxed?Array)
   Q. じゃあ UArray って何?
   A.?Array 遅い!って人のために。


   UArray はポインタを介さない分 Array よりアクセ
     スが速い&場所とらない。
   速さとヒープ領域を気にするならこっち使いましょ
     う。



      ?          ?
Agenda
   とりあえず普通の配列( Array,?UArray )
   O(1) で変更できなきゃ配列じゃない! (IOArray,?
     IOUArray)
   型クラスの話をしよう (IArray,?MArray)




      ?         ?
「 Array と参照透明性」
             に関する孔明の罠
   さっき (//) という「更新」演算子がでてきた。
   でも、 Haskell の関数は(基本的には)参照透明性
     が成り立ってなければならない。
   参照透明性 : 関数と引数の組によって、返り値が
     一意に決まる。




      ?       ?
「 Array と参照透明性」
                     に関する孔明の罠
   つまり?
   ary?=?array?(1,?2)?[(1,?1),?(2,?2)]
    として、
               ary!1
               let?ary'?=?ary//[(1,?2)]?in
                  ary!1
   は同じ値であってほしいなければならない。



            ?                   ?
「 Array と参照透明性」
              に関する孔明の罠
   しかし、 ary を破壊的に更新してしまった場合、
     ary!1 が元の値を返すかどうかはわからない。
     ary!1 が更新前に評価されれば 1 が返り、
     ary!1 が更新後に評価されれば 2 が返る。
          → 参照透明性に反する!
          ary!1 はいつ評価しても同じ値を返さなければなら
            ない。




      ?          ?
「 Array と参照透明性」
             に関する孔明の罠
   じゃあどういう実装になってんの?
     → 単純に、 ary には変更を加えず
     ary' 用の配列を新しく作る。
     → これでどこをいつ参照しても矛盾は起きない。
     やったね(?)




      ?       ?
「 Array と参照透明性」
                 に関する孔明の罠
   …… なにもうまくいってません。
            問題 1 :そもそも「更新」じゃなくて「新規作成」演算
              子になってる
            問題 2 :計算量 O(sizeof(ary))
              →? プロコンでうっかり使ったりすると死ぬ
   結論: (//) は更新する演算子ではなく、更新され
     た配列を新規作成する演算子




         ?          ?
補足
   注 1 )ドキュメントにも Incremental?array?updates
     と書いてあってまぎらわしい。
   注 2 ) Data.Array.IArray には、「殆どの IArray の
     インスタンスにおいて更新には O(N) かかる」と
     書いてある。
   注 3 ) Data.Array.IArray の (//) 関数の仕様自体が
     O(N) の計算量に本質的に関わっているわけで
     はない。(実際、もっと速い更新を実現する
     DiffArray などの IArray インスタンスもある)

       ?          ?
うまい解決法はないか
   破壊的更新ができれば文句ない。
   Haskell で破壊的操作をうまく扱う方法として IO
     モナドがある。
   IO モナドの文脈中ならうまいこと破壊的操作を扱
      える。
    →?IO モナドの中でしか使えない配列を作れば万
     事解決!




      ?       ?
IOArray/IOUArray
   Data.Array.IO にどっちも定義されている。
   作成?参照?更新は全て IO アクション。
     → アクションの実行順序は保証されるので、参
     照と更新の順序が入れかわったりしない!




      ?        ?
IOArray/IOUArray
   作成: newArray(newArray_,?newListArray)
              newArray?(lb,?ub)?x? で、インデックスが lb ? ub の
                 x で初期化された配列を返すアクションを返す。
   参照: readArray
              readArray?ary?i で、 ary の i 番地の値を返すアクショ
                 ンを返す。
   更新: writeArray
              writeArray?ary?i?x で、 ary の i 番地の値を x に変更
                するアクションを返す。

           ?              ?
IOArray/IOUArray
   使い方
   IO モナドの中で使う。
             do?ary?←?newArray?(1,?10)?0
                ??x?←?readArray?ary?1
                ??writeArray?ary?1?3
                ??y?←?readArray?ary?1
                ??...
   x,?y? には 0,?3 がそれぞれ束縛される。



          ?                ?
参照透明性は?
   さっきのプログラムの 2 つの readArray?ary?1 って
     別々の値を返してね?
     → readArray?ary?1 はあくまで両方「 ary からイン
     デックス i の値を取り出す操作」を表すアクション
     なのであって、 x,?y を返す関数ではありません。




       ?        ?
Pros?&?Cons
   正真正銘の O(1) 更新が可能!
   ただ、 IO に汚染される上、インタフェースが多少め
     んどい。




      ?      ?
備考
   IOArray 以外にも、 STArray など破壊的代入がで
      きる配列はある。
   IO モナドと違い ST モナドは外に脱出できるの
      で、 IO 操作を他に使わないならこっちのほうが
      いいかも。
             IOArray と使い勝手は一緒




          ?           ?
補足( 1 )
   thaw/freeze 関数を用いて普通の配列と可変配列
      との相互変換もできる。
   thaw (解凍)が Immutable?→?Mutable の変換
   freeze (凍結)が Mutable?→?Immutable の変換




       ?         ?
補足( 2 )
   もちろん thaw も freeze も O(N) 。
              ドキュメントにもちゃんと” by?taking?a?complete?copy?
                of?it.” とある。
   こういうときこそ STArray 使うといいかもしれない。
              手前味噌ですが STUArray を用いたエラトステネス
                の篩実装例
                http://d.hatena.ne.jp/g940425/20110827/1314442246
                      後半で unsafe な関数使ってるけど……こういう使い
                        かたなら問題ないはず。



           ?                ?
Agenda
   とりあえず普通の配列( Array,?UArray )
   O(1) で変更できなきゃ配列じゃない! (IOArray,?
     IOUArray)
   型クラスの話をしよう (IArray,?MArray)




      ?         ?
抽象化したい!
   Uarray と Array 、 IOUArray と IOArray は Box 化 /
     非 Box 化の違いでしかない。
     → これらの違いを無視した一般的なインタ
     フェースの関数を書きたい。




       ?           ?
例えば……




   sumA : Int 要素を持つ Array の全要素の和



      ?        ?
例えば……




   sumA をそのまま UArray に使おうとすると、当然の
      ように型エラーで怒られる。


      ?       ?
例えば……




   型ごとに関数を用意すればお k !



      ?      ?
いやいや
      <「お k !」じゃねえ!
       関数本体全く同じじゃねえか!
   こういう、形がほとんど同じ関数を連ねるのを
     「ボイラープレート( boilerplate )」という
     → Haskeller が最も嫌うもの
                   私も大嫌いです



   形が同じなら、まとめてかけるはず



      ?        ?
IArray/MArray
   変更不可配列 (Immutable?Array) を抽象する型ク
     ラスが IArray
   可変配列 (Mutable?Array) を抽象する型クラスが
     MArray
   型クラス: Iarray/MArray はそれ自体「型」ではな
     い( IArray? ? 型の値、は存在しない)




      ?        ?
IArray/MArray
   IArray?a?e : e 型の要素を持つ変更不可配列 a
   Marray?a?e?m : m モナドのコンテクストで変更可能
     な、 e 型の要素を持つ配列 a




      ?        ?
例ふたたび




   IArray を使って sumA を抽象化
   GHC 拡張 FlexibleContexts が必要(理由は後述)


      ?         ?
例ふたたび
   sumA?::?IArray?a?Int?=>?…
    → 「 a が Int を要素に持つ変更不可配列」
     という型制約をかけている
   sumA?::?…?=>?a?Int?Int?→?Int
      →?a?Int?Int?→?Int という型を持つので、
      a として当てはまる(= IArray?a?Int というインス
      タンスが宣言されている)もの全てに適用可能




        ?            ?
例ふたたび
   Data.Array.IArray にインスタンスとして
             IArray?Array?e
             IArray?UArray?Int
    が宣言されている。( e は型変数で、なんでもよい)
     → a が Array でも UArray でも型が合う!
             IArray?Array?Int?=>?Array?Int?Int?→?Int
               OK !:インスタンス IArray Array e がある


             IArray?UArray?Int?=>?UArray?Int?Int?→?Int
               OK !:インスタンス IArray UArray Int がある



          ?                  ?
補足( 3 )
   Q. かける制約は IArray?a?e でよかったのでは?
   A. 実は、 IArray?UArray?e という要素の型 e につい
     て一般化されたインスタンスはない。
     (Data.Array.UArray のドキュメント参照)
     → なのでこの例では IArray?a?Int のインスタンス
     宣言を使っており、そのため制約が IArray?a?Int
     となっている。
             IArray?Array?e?=>?Array?Int?Int?→?Int
               OK !:インスタンス IArray Array e がある


             IArray?UArray?e?=>?UArray?Int?Int?→?Int
               NG !:インスタンス IArray UArray e はない
          ?                 ?
補足( 4 )
   本来、型制約に具体的な型を入れることはできな
     い。
     → IArray?a?Int という制約はふつう許されない。
   これを許可するのが FlexibleContexts 拡張




      ?         ?
総括
   Haskell でも普通に配列使える
   しかし、速いプログラムにするには工夫が要る
     →使えるところでは Unboxed な配列を使う、とか
   抽象化もできる
     → ただ、なんでもかんでも抽象化すればいいと
     いうわけじゃない。 Lazy/Strict が本質的な場面
     もあるだろうし、競技プログラミングでわざわざ
     使いもしないのに抽象化した関数を書くのは得
     策でない。


      ?       ?
より進んだ話題
   Haskell には並列処理用行列
     repa ( [hackage]http://hackage.haskell.org/packa
     ge/repa )という、データ並列プログラミングをサ
     ポートする特殊なライブラリもある。
     → 配列というよりは「行列」
     → ついこの間( 2012/9/24 ) GHC?7.6 にも対応
   DiffArray なんてのもある( Immutable かつ更新も
     それなりに速い)
     [hackage]http://hackage.haskell.org/package/diffa
     rray

        ?            ?

More Related Content

What's hot (20)

コードゴルフのススメ(颁言语)
コードゴルフのススメ(颁言语)コードゴルフのススメ(颁言语)
コードゴルフのススメ(颁言语)
Fumihito Yokoyama
?
组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门
组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门
组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门
Norishige Fukushima
?
色々なタ?イクストラ高速化
色々なタ?イクストラ高速化色々なタ?イクストラ高速化
色々なタ?イクストラ高速化
yosupo
?
たのしい高阶関数
たのしい高阶関数たのしい高阶関数
たのしい高阶関数
Shinichi Kozake
?
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
kakira9618
?
C#でわかる こわくないMonad
C#でわかる こわくないMonadC#でわかる こわくないMonad
C#でわかる こわくないMonad
Kouji Matsui
?
厂蚕尝アンチパターン~スパゲッティクエリ
厂蚕尝アンチパターン~スパゲッティクエリ厂蚕尝アンチパターン~スパゲッティクエリ
厂蚕尝アンチパターン~スパゲッティクエリ
Itabashi Masayuki
?
プログラミングコンテストでのデータ构造
プログラミングコンテストでのデータ构造プログラミングコンテストでのデータ构造
プログラミングコンテストでのデータ构造
Takuya Akiba
?
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話
Nagisa Eto
?
SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更
T. Suwa
?
数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由
Hiromi Ishii
?
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説
AtCoder Inc.
?
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
?
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
Moriharu Ohzu
?
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
Tsuyoshi Matsudate
?
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
Hibiki Yamashiro
?
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
Genya Murakami
?
Nazoki
NazokiNazoki
Nazoki
Ken Ogura
?
Scala の関数型フ?ロク?ラミンク?を支える技術
Scala の関数型フ?ロク?ラミンク?を支える技術Scala の関数型フ?ロク?ラミンク?を支える技術
Scala の関数型フ?ロク?ラミンク?を支える技術
Naoki Aoyama
?
コードゴルフのススメ(颁言语)
コードゴルフのススメ(颁言语)コードゴルフのススメ(颁言语)
コードゴルフのススメ(颁言语)
Fumihito Yokoyama
?
组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门
组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门
组み込み関数(颈苍迟谤颈苍蝉颈肠)による厂滨惭顿入门
Norishige Fukushima
?
色々なタ?イクストラ高速化
色々なタ?イクストラ高速化色々なタ?イクストラ高速化
色々なタ?イクストラ高速化
yosupo
?
C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)C言語ポインタ講座 (Lecture of Pointer in C)
C言語ポインタ講座 (Lecture of Pointer in C)
kakira9618
?
C#でわかる こわくないMonad
C#でわかる こわくないMonadC#でわかる こわくないMonad
C#でわかる こわくないMonad
Kouji Matsui
?
厂蚕尝アンチパターン~スパゲッティクエリ
厂蚕尝アンチパターン~スパゲッティクエリ厂蚕尝アンチパターン~スパゲッティクエリ
厂蚕尝アンチパターン~スパゲッティクエリ
Itabashi Masayuki
?
プログラミングコンテストでのデータ构造
プログラミングコンテストでのデータ构造プログラミングコンテストでのデータ构造
プログラミングコンテストでのデータ构造
Takuya Akiba
?
Rolling Hashを殺す話
Rolling Hashを殺す話Rolling Hashを殺す話
Rolling Hashを殺す話
Nagisa Eto
?
SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更
T. Suwa
?
数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由数学プログラムを Haskell で書くべき 6 の理由
数学プログラムを Haskell で書くべき 6 の理由
Hiromi Ishii
?
AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説AtCoder Beginner Contest 023 解説
AtCoder Beginner Contest 023 解説
AtCoder Inc.
?
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
Moriharu Ohzu
?
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
Tsuyoshi Matsudate
?
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
竞技フ?ロク?ラミンク?におけるコート?の书き方とその利便性
Hibiki Yamashiro
?
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
Genya Murakami
?
Scala の関数型フ?ロク?ラミンク?を支える技術
Scala の関数型フ?ロク?ラミンク?を支える技術Scala の関数型フ?ロク?ラミンク?を支える技術
Scala の関数型フ?ロク?ラミンク?を支える技術
Naoki Aoyama
?

Viewers also liked (20)

Xenophobia
XenophobiaXenophobia
Xenophobia
alminarcomenius11
?
Xenophobia
XenophobiaXenophobia
Xenophobia
Greenwood Elementary School
?
Xenophobia Talk
Xenophobia TalkXenophobia Talk
Xenophobia Talk
humanrights
?
Diff
DiffDiff
Diff
Tatsuhiko Kubo
?
贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料
時響 逢坂
?
贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料
時響 逢坂
?
Windows 8 UX Guidelines
Windows 8 UX GuidelinesWindows 8 UX Guidelines
Windows 8 UX Guidelines
Takaaki Suzuki
?
Xenophobia 2
Xenophobia 2Xenophobia 2
Xenophobia 2
Gema De La Torre
?
すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料
Hiromasa Ohashi
?
ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果
Shu Takeda
?
驰别蝉辞诲勉强会
驰别蝉辞诲勉强会驰别蝉辞诲勉强会
驰别蝉辞诲勉强会
Hideyuki Tanaka
?
INTERCULTURAL COMMUNICATION COMPETENCE
INTERCULTURAL COMMUNICATION COMPETENCEINTERCULTURAL COMMUNICATION COMPETENCE
INTERCULTURAL COMMUNICATION COMPETENCE
???? ???????
?
【アップロードテスト】データマイニング入门编冲201501
【アップロードテスト】データマイニング入门编冲201501【アップロードテスト】データマイニング入门编冲201501
【アップロードテスト】データマイニング入门编冲201501
takosumipasta
?
すごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつり
すごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつりすごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつり
すごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつり
cohama
?
プラグインだけじゃない!そのままでもすごい惫颈尘
プラグインだけじゃない!そのままでもすごい惫颈尘プラグインだけじゃない!そのままでもすごい惫颈尘
プラグインだけじゃない!そのままでもすごい惫颈尘
Keisuke Izumiya
?
「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策
「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策
「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策
Hironori Miura
?
Globalization Of Health Care Final Star
Globalization Of Health Care Final StarGlobalization Of Health Care Final Star
Globalization Of Health Care Final Star
Herman D. Smith
?
すこ?いタスク管理(仮)
すこ?いタスク管理(仮)すこ?いタスク管理(仮)
すこ?いタスク管理(仮)
Kakigi Katuyuki
?
补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」
补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」
补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」
政樹 尾野
?
この滨搁のグラフがすごい!上场公司2015
この滨搁のグラフがすごい!上场公司2015この滨搁のグラフがすごい!上场公司2015
この滨搁のグラフがすごい!上场公司2015
itoyan110
?
贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料
時響 逢坂
?
贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料贰办尘别迟迟勉强会発表资料
贰办尘别迟迟勉强会発表资料
時響 逢坂
?
すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料
Hiromasa Ohashi
?
ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果
Shu Takeda
?
INTERCULTURAL COMMUNICATION COMPETENCE
INTERCULTURAL COMMUNICATION COMPETENCEINTERCULTURAL COMMUNICATION COMPETENCE
INTERCULTURAL COMMUNICATION COMPETENCE
???? ???????
?
【アップロードテスト】データマイニング入门编冲201501
【アップロードテスト】データマイニング入门编冲201501【アップロードテスト】データマイニング入门编冲201501
【アップロードテスト】データマイニング入门编冲201501
takosumipasta
?
すごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつり
すごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつりすごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつり
すごい痴颈尘で丑补蝉办别濒濒を书こう蔼なごやまつり
cohama
?
プラグインだけじゃない!そのままでもすごい惫颈尘
プラグインだけじゃない!そのままでもすごい惫颈尘プラグインだけじゃない!そのままでもすごい惫颈尘
プラグインだけじゃない!そのままでもすごい惫颈尘
Keisuke Izumiya
?
「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策
「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策
「360°スコ?イ」を創るVOYAGE GROUPエンシ?ニア成長施策
Hironori Miura
?
Globalization Of Health Care Final Star
Globalization Of Health Care Final StarGlobalization Of Health Care Final Star
Globalization Of Health Care Final Star
Herman D. Smith
?
すこ?いタスク管理(仮)
すこ?いタスク管理(仮)すこ?いタスク管理(仮)
すこ?いタスク管理(仮)
Kakigi Katuyuki
?
补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」
补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」
补濒迟闯厂勉强会「贬补虫别すごいからみんな使え!」
政樹 尾野
?
この滨搁のグラフがすごい!上场公司2015
この滨搁のグラフがすごい!上场公司2015この滨搁のグラフがすごい!上场公司2015
この滨搁のグラフがすごい!上场公司2015
itoyan110
?

Similar to すごい配列楽しく学ぼう (12)

scala.collection 再入門 (改)
scala.collection 再入門 (改)scala.collection 再入門 (改)
scala.collection 再入門 (改)
Ryuichi ITO
?
厂肠补濒补勉强会
厂肠补濒补勉强会厂肠补濒补勉强会
厂肠补濒补勉强会
omi end
?
Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)
Eugene Yokota
?
闯补惫补プログラミング入门【第7回】
闯补惫补プログラミング入门【第7回】闯补惫补プログラミング入门【第7回】
闯补惫补プログラミング入门【第7回】
Yukiko Kato
?
Scalaz
ScalazScalaz
Scalaz
Kota Mizushima
?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
Hiromi Ishii
?
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
Shinichi Kozake
?
搁厂辫别肠のここがすごい!
搁厂辫别肠のここがすごい!搁厂辫别肠のここがすごい!
搁厂辫别肠のここがすごい!
mitim
?
ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章
Yuta Yokoi
?
scala.collection 再入門 (改)
scala.collection 再入門 (改)scala.collection 再入門 (改)
scala.collection 再入門 (改)
Ryuichi ITO
?
厂肠补濒补勉强会
厂肠补濒补勉强会厂肠补濒补勉强会
厂肠补濒补勉强会
omi end
?
Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)
Eugene Yokota
?
闯补惫补プログラミング入门【第7回】
闯补惫补プログラミング入门【第7回】闯补惫补プログラミング入门【第7回】
闯补惫补プログラミング入门【第7回】
Yukiko Kato
?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?How wonderful to be (statically) typed ?型が付くってスバラシイ?
How wonderful to be (statically) typed ?型が付くってスバラシイ?
Hiromi Ishii
?
搁厂辫别肠のここがすごい!
搁厂辫别肠のここがすごい!搁厂辫别肠のここがすごい!
搁厂辫别肠のここがすごい!
mitim
?
ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章
Yuta Yokoi
?

すごい配列楽しく学ぼう

  • 1. すごい配列楽しく学ぼう ~ Haskell の配列事情 ~ @xenophobia__ ? ?
  • 2. テーマについて 勉強会をやるらしい → 各 λ 人の好きな題材でいいらしい。 → じゃあ Haskell で何か話そう。 → でもすごい H 本出たし基本的なことはもう話題と して出尽してるよな…… → あれ?この本配列について書いてなくね? →?λ < Haskell の配列も楽しく学ぼう! ? ?
  • 3. Haskell とは!  なんてことを話している時間はない。  とりあえず今後の話に関わることとしてこれぐらい。  型に厳しい(強い静的型付けである)  キャストとかゆとりな事はしない  型が合ってないと絶対許してくれない  参照透明性が(基本的には)成り立つ  IO ?破壊的変更の扱いがめんどい特殊  unsafe ほげほげの話はしない  「型クラス」がある  「型クラス」は共通の性質を持った型の集まり  ある型クラスに関して polymorphic な関数とか書ける ? ?
  • 4. Haskell の配列について  Haskell では、コレクションは普通リスト型で扱う。  配列はあんまり話題にならない気がする(すごい H 本にも記述は多分ない? RHW にはあった)  調べるといろいろ (Array,?UArray,?IArray,?MArray,? IOArray,?...) でてきてよくわからない。  でも……  プロコンとかだと使いたい。  できるだけ速いほうがいい。 ? ?
  • 5. Agenda  とりあえず普通の配列( Array,?UArray )  O(1) で変更できなきゃ配列じゃない! (IOArray,? IOUArray)  型クラスの話をしよう (IArray,?MArray) ? ?
  • 6. Agenda  とりあえず普通の配列( Array,?UArray )  O(1) で変更できなきゃ配列じゃない! (IOArray,? IOUArray)  型クラスの話をしよう (IArray,?MArray) ? ?
  • 7. Haskell 標準の配列を使う  Array,?UArray (違いはあとで。)  Array は Data.Array( または Data.Array.IArray) に ある。  UArray は Data.Array.Unboxed にある。 ? ?
  • 8. Haskell 標準の配列を使う  配列を作るには? →?array 関数を使う(或いは listArray )  array?(0,?3)?[(0,?1),?(1,?2),?(2,?4),?(3,?9)]  array?((1,?1),?(2,?2))?[((1,1),?'a'),?((1,2),?'a'),?((2,1),?'z'),? ((2,2),?'d')]  listArray?(1,?100)?[0,?0?..]  インデックスには、 Int,?Char 及びそのタプルなどが 使える。  厳密には Ix 型クラスのインスタンスがすべて使える。 ここでは説明は省略。 ? ?
  • 9. Haskell 標準の配列を使う  型は?  C などと違い、インデックスもいろいろ使える。 → インデックスも型パラメタとして与える。  インデックスが Int で要素が String の Array なら、 Array?Int?String? となる。  インデックスが (Char,?Char) で要素が Int の UArray なら、 UArray?(Char,?Char)?Int となる。 ? ?
  • 10. Haskell 標準の配列を使う  配列 ary の要素にアクセスしたい → (!) 演算子  例) let?x?=?ary!2?in?… ???????let?x?=?ary!(0,?3)?in?…  配列 ary の要素を更新したい → (//) 演算子  例) let?ary'?=?ary//[(1,?2),?(3,?0)] ???ary[1] を 2 に、 ary[3] を 0 に更新  ただし、これには後に述べるように罠が隠れている。 ? ?
  • 11. Array/UArray の違いって?  Array 型と UArray 型は、使い方はほぼ同じ。  じゃあ違いは?  Array は Box 化されている  Uarray は Box 化されていない  (? ? _ ? `) ? < おまえは なにを いってるんだ ? ?
  • 12. Array/UArray の違いって?  つまり  Array は、オブジェクトへのポインタを持った配列  UArray は、値そのものを入れる配列  もっと言うと  Array は Lazy な配列  UArray は Strict な配列 ? ?
  • 13. Array/UArray の違いって?  Array の要素を参照するときの動作  ポインタが示す先に行き、オブジェクトを返す  そのオブジェクトの値が必要になったら評価する。  もちろん、オブジェクトが評価済みならその値自体を 返す。 0 1 未評価 評価済み Eval 2 10 * 10 100 3 ? ?
  • 15. なんでそんなことになってんの?  …… ではさすがにあんまりなので。  Array が正格評価する仕様だと、例えば変数 x,?y,? z を用いて ary?=?array?(1,?3)?[(1,?x),?(2,?y),?(3,?z)] のようにに配列を作ると、 x,?y,?z は配列作成時に 全て評価されなければならない。(評価しないと 格納する値がわからない) ? ?
  • 16. なんでそんなことになってんの?  「 x を配列に入れる」というロジックに「 x を評価す る」ことは必要か?  たとえば ary のうち一つの要素にしかアクセスしな いかもしれない。 → 「アクセスしない=使わない」ってことじゃない の? ? ?
  • 17. なんでそんなことになってんの?  λ <使わないのに評価されるのは遅延評価とし ておかしい!( Haskell は call?by?need の遅延評 価!)  要素が何であるかの評価は、実際にその要素の値 が必要になるまで遅延するのがよい! てな感じなんじゃないですかね。知らんけど…… ? ?
  • 18. UArray(Unboxed?Array)  Q. じゃあ UArray って何?  A.?Array 遅い!って人のために。  UArray はポインタを介さない分 Array よりアクセ スが速い&場所とらない。  速さとヒープ領域を気にするならこっち使いましょ う。 ? ?
  • 19. Agenda  とりあえず普通の配列( Array,?UArray )  O(1) で変更できなきゃ配列じゃない! (IOArray,? IOUArray)  型クラスの話をしよう (IArray,?MArray) ? ?
  • 20. 「 Array と参照透明性」 に関する孔明の罠  さっき (//) という「更新」演算子がでてきた。  でも、 Haskell の関数は(基本的には)参照透明性 が成り立ってなければならない。  参照透明性 : 関数と引数の組によって、返り値が 一意に決まる。 ? ?
  • 21. 「 Array と参照透明性」 に関する孔明の罠  つまり?  ary?=?array?(1,?2)?[(1,?1),?(2,?2)] として、  ary!1  let?ary'?=?ary//[(1,?2)]?in ary!1  は同じ値であってほしいなければならない。 ? ?
  • 22. 「 Array と参照透明性」 に関する孔明の罠  しかし、 ary を破壊的に更新してしまった場合、 ary!1 が元の値を返すかどうかはわからない。 ary!1 が更新前に評価されれば 1 が返り、 ary!1 が更新後に評価されれば 2 が返る。 → 参照透明性に反する! ary!1 はいつ評価しても同じ値を返さなければなら ない。 ? ?
  • 23. 「 Array と参照透明性」 に関する孔明の罠  じゃあどういう実装になってんの? → 単純に、 ary には変更を加えず ary' 用の配列を新しく作る。 → これでどこをいつ参照しても矛盾は起きない。 やったね(?) ? ?
  • 24. 「 Array と参照透明性」 に関する孔明の罠  …… なにもうまくいってません。  問題 1 :そもそも「更新」じゃなくて「新規作成」演算 子になってる  問題 2 :計算量 O(sizeof(ary)) →? プロコンでうっかり使ったりすると死ぬ  結論: (//) は更新する演算子ではなく、更新され た配列を新規作成する演算子 ? ?
  • 25. 補足  注 1 )ドキュメントにも Incremental?array?updates と書いてあってまぎらわしい。  注 2 ) Data.Array.IArray には、「殆どの IArray の インスタンスにおいて更新には O(N) かかる」と 書いてある。  注 3 ) Data.Array.IArray の (//) 関数の仕様自体が O(N) の計算量に本質的に関わっているわけで はない。(実際、もっと速い更新を実現する DiffArray などの IArray インスタンスもある) ? ?
  • 26. うまい解決法はないか  破壊的更新ができれば文句ない。  Haskell で破壊的操作をうまく扱う方法として IO モナドがある。  IO モナドの文脈中ならうまいこと破壊的操作を扱 える。 →?IO モナドの中でしか使えない配列を作れば万 事解決! ? ?
  • 27. IOArray/IOUArray  Data.Array.IO にどっちも定義されている。  作成?参照?更新は全て IO アクション。 → アクションの実行順序は保証されるので、参 照と更新の順序が入れかわったりしない! ? ?
  • 28. IOArray/IOUArray  作成: newArray(newArray_,?newListArray)  newArray?(lb,?ub)?x? で、インデックスが lb ? ub の x で初期化された配列を返すアクションを返す。  参照: readArray  readArray?ary?i で、 ary の i 番地の値を返すアクショ ンを返す。  更新: writeArray  writeArray?ary?i?x で、 ary の i 番地の値を x に変更 するアクションを返す。 ? ?
  • 29. IOArray/IOUArray  使い方  IO モナドの中で使う。  do?ary?←?newArray?(1,?10)?0 ??x?←?readArray?ary?1 ??writeArray?ary?1?3 ??y?←?readArray?ary?1 ??...  x,?y? には 0,?3 がそれぞれ束縛される。 ? ?
  • 30. 参照透明性は?  さっきのプログラムの 2 つの readArray?ary?1 って 別々の値を返してね? → readArray?ary?1 はあくまで両方「 ary からイン デックス i の値を取り出す操作」を表すアクション なのであって、 x,?y を返す関数ではありません。 ? ?
  • 31. Pros?&?Cons  正真正銘の O(1) 更新が可能!  ただ、 IO に汚染される上、インタフェースが多少め んどい。 ? ?
  • 32. 備考  IOArray 以外にも、 STArray など破壊的代入がで きる配列はある。  IO モナドと違い ST モナドは外に脱出できるの で、 IO 操作を他に使わないならこっちのほうが いいかも。  IOArray と使い勝手は一緒 ? ?
  • 33. 補足( 1 )  thaw/freeze 関数を用いて普通の配列と可変配列 との相互変換もできる。  thaw (解凍)が Immutable?→?Mutable の変換  freeze (凍結)が Mutable?→?Immutable の変換 ? ?
  • 34. 補足( 2 )  もちろん thaw も freeze も O(N) 。  ドキュメントにもちゃんと” by?taking?a?complete?copy? of?it.” とある。  こういうときこそ STArray 使うといいかもしれない。  手前味噌ですが STUArray を用いたエラトステネス の篩実装例 http://d.hatena.ne.jp/g940425/20110827/1314442246  後半で unsafe な関数使ってるけど……こういう使い かたなら問題ないはず。 ? ?
  • 35. Agenda  とりあえず普通の配列( Array,?UArray )  O(1) で変更できなきゃ配列じゃない! (IOArray,? IOUArray)  型クラスの話をしよう (IArray,?MArray) ? ?
  • 36. 抽象化したい!  Uarray と Array 、 IOUArray と IOArray は Box 化 / 非 Box 化の違いでしかない。 → これらの違いを無視した一般的なインタ フェースの関数を書きたい。 ? ?
  • 37. 例えば……  sumA : Int 要素を持つ Array の全要素の和 ? ?
  • 38. 例えば……  sumA をそのまま UArray に使おうとすると、当然の ように型エラーで怒られる。 ? ?
  • 39. 例えば……  型ごとに関数を用意すればお k ! ? ?
  • 40. いやいや <「お k !」じゃねえ! 関数本体全く同じじゃねえか!  こういう、形がほとんど同じ関数を連ねるのを 「ボイラープレート( boilerplate )」という → Haskeller が最も嫌うもの 私も大嫌いです  形が同じなら、まとめてかけるはず ? ?
  • 41. IArray/MArray  変更不可配列 (Immutable?Array) を抽象する型ク ラスが IArray  可変配列 (Mutable?Array) を抽象する型クラスが MArray  型クラス: Iarray/MArray はそれ自体「型」ではな い( IArray? ? 型の値、は存在しない) ? ?
  • 42. IArray/MArray  IArray?a?e : e 型の要素を持つ変更不可配列 a  Marray?a?e?m : m モナドのコンテクストで変更可能 な、 e 型の要素を持つ配列 a ? ?
  • 43. 例ふたたび  IArray を使って sumA を抽象化  GHC 拡張 FlexibleContexts が必要(理由は後述) ? ?
  • 44. 例ふたたび  sumA?::?IArray?a?Int?=>?… → 「 a が Int を要素に持つ変更不可配列」 という型制約をかけている  sumA?::?…?=>?a?Int?Int?→?Int →?a?Int?Int?→?Int という型を持つので、 a として当てはまる(= IArray?a?Int というインス タンスが宣言されている)もの全てに適用可能 ? ?
  • 45. 例ふたたび  Data.Array.IArray にインスタンスとして  IArray?Array?e  IArray?UArray?Int が宣言されている。( e は型変数で、なんでもよい) → a が Array でも UArray でも型が合う!  IArray?Array?Int?=>?Array?Int?Int?→?Int OK !:インスタンス IArray Array e がある  IArray?UArray?Int?=>?UArray?Int?Int?→?Int OK !:インスタンス IArray UArray Int がある ? ?
  • 46. 補足( 3 )  Q. かける制約は IArray?a?e でよかったのでは?  A. 実は、 IArray?UArray?e という要素の型 e につい て一般化されたインスタンスはない。 (Data.Array.UArray のドキュメント参照) → なのでこの例では IArray?a?Int のインスタンス 宣言を使っており、そのため制約が IArray?a?Int となっている。  IArray?Array?e?=>?Array?Int?Int?→?Int OK !:インスタンス IArray Array e がある  IArray?UArray?e?=>?UArray?Int?Int?→?Int NG !:インスタンス IArray UArray e はない ? ?
  • 47. 補足( 4 )  本来、型制約に具体的な型を入れることはできな い。 → IArray?a?Int という制約はふつう許されない。  これを許可するのが FlexibleContexts 拡張 ? ?
  • 48. 総括  Haskell でも普通に配列使える  しかし、速いプログラムにするには工夫が要る →使えるところでは Unboxed な配列を使う、とか  抽象化もできる → ただ、なんでもかんでも抽象化すればいいと いうわけじゃない。 Lazy/Strict が本質的な場面 もあるだろうし、競技プログラミングでわざわざ 使いもしないのに抽象化した関数を書くのは得 策でない。 ? ?
  • 49. より進んだ話題  Haskell には並列処理用行列 repa ( [hackage]http://hackage.haskell.org/packa ge/repa )という、データ並列プログラミングをサ ポートする特殊なライブラリもある。 → 配列というよりは「行列」 → ついこの間( 2012/9/24 ) GHC?7.6 にも対応  DiffArray なんてのもある( Immutable かつ更新も それなりに速い) [hackage]http://hackage.haskell.org/package/diffa rray ? ?