SlideShare une entreprise Scribd logo
1  sur  49
Télécharger pour lire hors ligne
すごい配列楽しく学ぼう
     ~ 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

                      

Contenu connexe

Tendances

SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更T. Suwa
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Preferred Networks
 
[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...
[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...
[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...Deep Learning JP
 
最適化計算の概要まとめ
最適化計算の概要まとめ最適化計算の概要まとめ
最適化計算の概要まとめYuichiro MInato
 
MapReduceによる大規模データを利用した機械学習
MapReduceによる大規模データを利用した機械学習MapReduceによる大規模データを利用した機械学習
MapReduceによる大規模データを利用した機械学習Preferred Networks
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方Kensuke Otsuki
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~Takuya Akiba
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門大樹 小倉
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理Norishige Fukushima
 
自動定理証明の紹介
自動定理証明の紹介自動定理証明の紹介
自動定理証明の紹介Masahiro Sakai
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門Yoichi Iwata
 
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造Takuya Akiba
 
技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底Hiromi Ishii
 

Tendances (20)

SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更SATySFi 最近の発展と目下実装中の変更
SATySFi 最近の発展と目下実装中の変更
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
Binary indexed tree
Binary indexed treeBinary indexed tree
Binary indexed tree
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
 
[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...
[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...
[DL輪読会]Set Transformer: A Framework for Attention-based Permutation-Invariant...
 
最適化計算の概要まとめ
最適化計算の概要まとめ最適化計算の概要まとめ
最適化計算の概要まとめ
 
MapReduceによる大規模データを利用した機械学習
MapReduceによる大規模データを利用した機械学習MapReduceによる大規模データを利用した機械学習
MapReduceによる大規模データを利用した機械学習
 
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
二部グラフの最小点被覆と最大安定集合と最小辺被覆の求め方
 
プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~プログラミングコンテストでのデータ構造 2 ~動的木編~
プログラミングコンテストでのデータ構造 2 ~動的木編~
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理
 
Chokudai search
Chokudai searchChokudai search
Chokudai search
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 
自動定理証明の紹介
自動定理証明の紹介自動定理証明の紹介
自動定理証明の紹介
 
指数時間アルゴリズム入門
指数時間アルゴリズム入門指数時間アルゴリズム入門
指数時間アルゴリズム入門
 
蟻本輪講 データ構造
蟻本輪講 データ構造蟻本輪講 データ構造
蟻本輪講 データ構造
 
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
 
技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底技術者が知るべき Gröbner 基底
技術者が知るべき Gröbner 基底
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 

En vedette

Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Windows 8 UX Guidelines
Windows 8 UX GuidelinesWindows 8 UX Guidelines
Windows 8 UX GuidelinesTakaaki Suzuki
 
すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料Hiromasa Ohashi
 
ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果Shu Takeda
 
【アップロードテスト】データマイニング入門編_201501
【アップロードテスト】データマイニング入門編_201501【アップロードテスト】データマイニング入門編_201501
【アップロードテスト】データマイニング入門編_201501takosumipasta
 
すごいVimでhaskellを書こう@なごやまつり
すごいVimでhaskellを書こう@なごやまつりすごいVimでhaskellを書こう@なごやまつり
すごいVimでhaskellを書こう@なごやまつりcohama
 
プラグインだけじゃない!そのままでもすごいvim
プラグインだけじゃない!そのままでもすごいvimプラグインだけじゃない!そのままでもすごいvim
プラグインだけじゃない!そのままでもすごいvimKeisuke 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 StarHerman D. Smith
 
すごいタスク管理(仮)
すごいタスク管理(仮)すごいタスク管理(仮)
すごいタスク管理(仮)Kakigi Katuyuki
 
altJS勉強会「Haxeすごいからみんな使え!」
altJS勉強会「Haxeすごいからみんな使え!」altJS勉強会「Haxeすごいからみんな使え!」
altJS勉強会「Haxeすごいからみんな使え!」政樹 尾野
 
このIRのグラフがすごい!上場企業2015
このIRのグラフがすごい!上場企業2015このIRのグラフがすごい!上場企業2015
このIRのグラフがすごい!上場企業2015itoyan110
 

En vedette (20)

Xenophobia
XenophobiaXenophobia
Xenophobia
 
Xenophobia
XenophobiaXenophobia
Xenophobia
 
Xenophobia Talk
Xenophobia TalkXenophobia Talk
Xenophobia Talk
 
Diff
DiffDiff
Diff
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Windows 8 UX Guidelines
Windows 8 UX GuidelinesWindows 8 UX Guidelines
Windows 8 UX Guidelines
 
Xenophobia 2
Xenophobia 2Xenophobia 2
Xenophobia 2
 
すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料
 
ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果ウォーキングとゆっくり呼吸のすごい効果
ウォーキングとゆっくり呼吸のすごい効果
 
Yesod勉強会
Yesod勉強会Yesod勉強会
Yesod勉強会
 
INTERCULTURAL COMMUNICATION COMPETENCE
INTERCULTURAL COMMUNICATION COMPETENCEINTERCULTURAL COMMUNICATION COMPETENCE
INTERCULTURAL COMMUNICATION COMPETENCE
 
【アップロードテスト】データマイニング入門編_201501
【アップロードテスト】データマイニング入門編_201501【アップロードテスト】データマイニング入門編_201501
【アップロードテスト】データマイニング入門編_201501
 
すごいVimでhaskellを書こう@なごやまつり
すごいVimでhaskellを書こう@なごやまつりすごいVimでhaskellを書こう@なごやまつり
すごいVimでhaskellを書こう@なごやまつり
 
プラグインだけじゃない!そのままでもすごいvim
プラグインだけじゃない!そのままでもすごいvimプラグインだけじゃない!そのままでもすごいvim
プラグインだけじゃない!そのままでもすごいvim
 
「360°スゴイ」を創るVOYAGE GROUPエンジニア成長施策
「360°スゴイ」を創るVOYAGE GROUPエンジニア成長施策「360°スゴイ」を創るVOYAGE GROUPエンジニア成長施策
「360°スゴイ」を創るVOYAGE GROUPエンジニア成長施策
 
Globalization Of Health Care Final Star
Globalization Of Health Care Final StarGlobalization Of Health Care Final Star
Globalization Of Health Care Final Star
 
すごいタスク管理(仮)
すごいタスク管理(仮)すごいタスク管理(仮)
すごいタスク管理(仮)
 
altJS勉強会「Haxeすごいからみんな使え!」
altJS勉強会「Haxeすごいからみんな使え!」altJS勉強会「Haxeすごいからみんな使え!」
altJS勉強会「Haxeすごいからみんな使え!」
 
このIRのグラフがすごい!上場企業2015
このIRのグラフがすごい!上場企業2015このIRのグラフがすごい!上場企業2015
このIRのグラフがすごい!上場企業2015
 

Similaire à すごい配列楽しく学ぼう

BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
scala.collection 再入門 (改)
scala.collection 再入門 (改)scala.collection 再入門 (改)
scala.collection 再入門 (改)Ryuichi ITO
 
Scala勉強会
Scala勉強会Scala勉強会
Scala勉強会omi end
 
Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Eugene Yokota
 
Javaプログラミング入門【第7回】
Javaプログラミング入門【第7回】Javaプログラミング入門【第7回】
Javaプログラミング入門【第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
 
RSpecのここがすごい!
RSpecのここがすごい!RSpecのここがすごい!
RSpecのここがすごい!mitim
 
ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章Yuta Yokoi
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 

Similaire à すごい配列楽しく学ぼう (13)

BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
scala.collection 再入門 (改)
scala.collection 再入門 (改)scala.collection 再入門 (改)
scala.collection 再入門 (改)
 
Scala勉強会
Scala勉強会Scala勉強会
Scala勉強会
 
Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)Equality in Scala (ScalaMatsuri 2020)
Equality in Scala (ScalaMatsuri 2020)
 
Javaプログラミング入門【第7回】
Javaプログラミング入門【第7回】Javaプログラミング入門【第7回】
Javaプログラミング入門【第7回】
 
Scalaz
ScalazScalaz
Scalaz
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
RSpecのここがすごい!
RSpecのここがすごい!RSpecのここがすごい!
RSpecのここがすごい!
 
ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章ゆるふわScalaコップ本読書会 第7章
ゆるふわScalaコップ本読書会 第7章
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 

すごい配列楽しく学ぼう

  • 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