SlideShare a Scribd company logo
@aomoriringo
1986-2005   ◎   Twitter: @aomoriringo

             ◎   最近使ってる言語
                 ◦ C#


             ◎   趣味
2005-2011        ◦ Mathematica


2011-        ◎   Haskell歴
                 ◦ 2ヶ月未満
◎   いくつかの関数や型、型クラスなどを定義したファイル

◎   Haskellのプログラムはモジュールの集合

◎   コードをモジュールに分割するとしあわせ
    ◦ 再利用性を高める
    ◦ 管理・修正しやすくする
◎   モジュールをインポートする

◎   標準モジュールを使ってみる
    ◦ 標準モジュールでいろいろ作ってみる
    ◦ foldl, foldl’
    ◦ 連想リスト


◎   自分でモジュールを作ってみる
モジュールをインポートする
◎   全てをインポート
    import Data.List



◎   nub, sortのみをインポート
    import Data.List (nub, sort)



◎   nub以外の全てをインポート
    import Data.List hiding (nub)
import qualified Data.Map
  ◦ Data.Map.filterのように参照



import qualified Data.Map as M
  ◦ M.filterのように参照
◎   module Fooにhogeとbarがあるとき
宣言                          インポートされるもの 参照の方法
import Foo                  hoge, bar   hoge, bar
                                        Foo.hoge, Foo.bar
import Foo ()               (なし)
import Foo (hoge)           hoge        hoge, Foo.hoge
import Foo hiding (hoge)    bar         bar, Foo.bar
import qualified Foo        hoge, bar   Foo.hoge, Foo.bar
import Foo as F             hoge, bar   hoge, bar
                                        F.hoge, F.bar
import qualified Foo as F   hoge, bar   F.hoge, F.bar
◎   Data.Listをインポート
ghci> :m + Data.List
ghci> :m + Data.List Data.Map Data.Set


◎   Data.Listのインポートを解除
ghci> :m – Data.List


◎   importも使用可能
ghci> import Data.List (nub, sort)
ghci> import qualified Data.Map as M hiding (foldl)
標準モジュールを使ってみる

       Data.List
       Data.Char
        Data.Map
◎   Hackage
    ◦ hackage.haskell.org/packages/hackage.html


◎   Hoogle
    ◦ http://www.haskell.org/hoogle/
    ◦ 標準モジュールのソースコードが見れます


◎   Hayoo!
    ◦ http://holumbus.fh-wedel.de/hayoo/hayoo.html
◎   単語の個数を調べる

ghci> :t wordNums
wordNums :: String -> [(String,Int)]

ghci> wordNums "a haskell learn haskell a a learn good"
[("a",3),("good",1),("haskell",2),("learn",2)]
◎   文字列を空白で区切られた文字列のリストに変換する

ghci> :t words
words :: String -> [String]

ghci> words “hey these are the words”
[“hey”, “these”, “are”, “the”, “words”]

ghci> words “hey     these   are the    words”
[“hey”, “these”, “are”, “the”, “words”]
◎   リストの同じ要素をグループ化する

ghci> :t group
group :: Eq a => [a] -> [[a]]

ghci> group [1,1,1,2,2,2,3,3,2,2,5,7]
[[1,1,1],[2,2,2],[3,3],[2,2],[5],[7]]

ghci> group [“hoge”, “var”, “var”, “hoge”, “hoge”]
[[“hoge”], [“var”, “var”], [“hoge”, “hoge”]]
◎   リストを昇順に並べ替える

ghci> :t sort
sort :: Ord a => [a] -> [a]

ghci> sort [5,4,3,7,2,1]
[1,2,3,4,5,7]

ghci> sort [“hoge”, “var”, “var”, “hoge”, “hoge”]
[“hoge”, “hoge”, “hoge”, “var”, “var”]
文字列を単語に区切って (words)

→ソートして (sort)

→グループ化して (group)

→グループごとに数を数えれば

できそうですね!
◎   wordNumsの定義
wordNums :: String -> [(String,Int)]
wordNums = map (¥ws -> (head ws, length ws)) .
           group . sort . words



ghci> wordNums “a b c b c”
[("a",1),(“b",2),(“c",2)]

ghci> wordNums “”
[]
◎   あるリストが別のリストに含まれるかどうかを調べる

ghci> :t isIn
isIn :: [a] -> [a] -> Bool

ghci> “art” `isIn` “party”
True

ghci> [1,2] `isIn` [1,3,5]
False
◎   リストに対してtailを繰り返し適用する

ghci> :t tails
tails :: [a] -> [[a]]

ghci> tails “party”
[“party”, “arty”, “rty”, “ty”, “y”, “”]

ghci> tails [1,2,3]
[[1,2,3], [2,3], [3], []]
◎   2つ目のリストが1つ目のリストで
    始まっているかどうかを返す
ghci> :t isPrefixOf
isPrefixOf :: String -> String -> Bool

ghci> “hawaii” `isPrefixOf` “hawaii joe”
True

ghci> “haha” `isPrefixOf` “ha”
False

ghci> “ha” `isPrefixOf` “haha”
True
“art” `isPrefixOf` “party”   -- False

“art” `isPrefixOf` “arty”    -- True

“art” `isPrefixOf` “rty”     -- False

“art” `isPrefixOf` “ty”      -- False

“art” `isPrefixOf` “y”       -- False
◎   リストのうち、述語を満たすものがあるかどうかを返す

ghci> :t any
any :: (a -> Bool) -> [a] -> Bool

ghci> any (>4) [1,2,3]
False

ghci> any id [False, False, True]
True
◎   isInの定義
isIn :: (Eq a) => [a] -> [a] -> Bool
needle `isIn` haystack =
      any (needle `isPrefixOf`) (tails haystack)



needle: 針。見つけたいリスト
haystack: 干し草の山。検索対象のリスト
◎   Data.List.isPrefixOf
    ◦ 前方一致
    ◦ さっき使った


◎   Data.List.isSuffixOf
    ◦ 後方一致


◎   Data.List.isInfixOf
    ◦ 中間一致
    ◦ さっき作った(isIn)
◎   シーザー暗号
    ◦ 平文の各文字を辞書順にn文字シフトして作る
◎   文字<->Unicode変換
ghci> :t ord
ord :: Char -> Int
ghci> ord ‘a’
97

ghci> :t chr
chr :: Int -> Char
ghci> chr 97
‘a’

ghci> map ord “abcdefgh”
[97,98,99,100,101,102,103,104]
◎   指定した文字数分シフトする
encode :: Int -> String -> String
encode offset msg =
            map (¥c -> chr $ ord c + offset) msg




◎   指定した文字数分逆にシフトする
decode :: Int -> String -> String
decode shift msg = encode (negate shift) msg
ghci> encode 3 “hey mark”
“kh|#pdun”

ghci> decode 3 “kh|#pdun”
“hey mark”

ghci> decode 3 $ encode 3 “abc”
“abc”
◎   各桁の数の合計がnになる最初の自然数をみつける

ghci> :t firstTo
firstTo :: Int -> Int

ghci> firstTo 1
1

ghci> firstTo 13
49
◎   文字を数に変換する

ghci> :t digitToInt
digitToInt :: Char -> Int

ghci> digitToInt ‘2’
2
ghci> digitToInt ‘F’
15
ghci> digitToInt ‘z’
*** Exception: Char.digitToInt: not a digit 'z'
◎   各桁の数の和を返す

digitSum :: Int -> Int
digitSum = sum . map digitToInt . show



ghci> digitSum 30
3
ghci> digitSum 1234
10
ghci> :t find
find :: (a -> Bool) -> [a] -> Maybe a

ghci> find (>4) [3,4,5,6,7]         Nothing | Just a
Just 5

ghci> find odd [2,4,6,8,9]
Just 9

ghci> find (==‘z’) “haskell”
Nothing
◎   firstToの定義
firstTo :: Int -> Maybe Int
firstTo n =
      find (¥x -> digitSum x == n) [1..]



ghci> firstTo 27
Just 999

ghci> firstTo 40
Just 49999
foldl, foldl’
ghci> foldl (+) 0 [1..2000000]
2000001000000
 ◦ 遅い
 ◦ サイズ、環境によってはスタックオーバーフロー


ghci> Data.List.foldl’ (+) 0 [1..2000000]
2000001000000
 ◦ foldlより速い
 ◦ オーバーフローしない
foldl (+) 0 [1,2,3] =
foldl (+) (0 + 1) [2,3] =
foldl (+) ((0 + 1) + 2) [3] =
foldl (+) (((0 + 1) + 2) + 3) [] =
((0 + 1) + 2) + 3 =
(1 + 2) + 3 =
3 + 3 =
6
◎   正格な(遅延でない)左畳み込み

foldl’   (+)   0   [1,2,3] =
foldl’   (+)   1   [2,3] =
foldl’   (+)   3   [3] =
foldl’   (+)   6   [] =
6
連想リスト
◎   添字として任意の型を使用する配列

◎   呼び方はいろいろ
    ◦ Map
    ◦ Dictionary
    ◦ Hash
◎   タプルを連想リストっぽく扱う
ghci> :t lookup
lookup :: Eq a => a -> [(a,b)] -> Maybe b

ghci> lookup “b” [(“a”,1), (“b”,2), (“c”,3)]
Just 2

ghci> lookup “k” [(“a”,1), (“b”,2), (“c”,3)]
Nothing
◎   連想リスト(Map)のモジュール
    ◦   Data.Map.lookup
    ◦   Data.Map.insert
    ◦   Data.Map.delete
    ◦   Data.Map.size
    ◦   etc..
◎ Data.Mapで連想リストを表す型
◎ keyとvalueの型を持つ


ghci> let m = Data.Map.fromList [(“foo”,1), (“bar”,2)]
ghci> :t m
m :: Data.Map.Map [Char] Integer

ghci> let m2 = Data.Map.fromList [(‘a’, True), (‘b’, False)]
ghci> :t m2
m2 :: Data.Map.Map Char Bool
ghci> import qualified Data.Map as Map


◎   keyで検索する
ghci> let m = Map.fromList [(“a”,1), (“b”,2)]
ghci> Map.lookup “b” m
Just 2
ghci> Map.lookup “c” m
Nothing


◎   key=“c”, value=3の要素を挿入する
ghci> let m2 = Map.insert “c” 3 m
ghci> Map.lookup “c” m2
Just 3

ghci> Map.size m2
3
◎   valueに関数を適用して新しいMapを作る

ghci> m2
fromList [("a",1),("b",2),("c",3)]

ghci> Map.map (^2) m2
fromList [("a",1),("b",4),("c",9)]

ghci> Map.map show m2
fromList [(“a”,”1”), (“b”,”2”), (“c”, “3”)]
◎   keyが重複した際の振る舞いを決める

ghci> Map.fromList [(1,2),(1,50),(1,10),(2,3)]
fromList [(1,10),(2,3)]

ghci> Map.fromListWith (+) [(1,2),(1,50),(1,10),(2,3)]
fromList [(1,62),(2,3)]

ghci> Map.fromListWith max [(1,2),(1,50),(1,10),(2,3)]
fromList [(1,50),(2,3)]
モジュールを作る
◎   先頭にモジュール宣言を書く
    -- Foo.hs
    module Foo where

    ◦ モジュール名とファイル名は同じにしなければならない

◎   モジュールの中身を
    ◦ 全て公開したい(エクスポート)
      module Foo where

    ◦ 一部だけ公開したい
    ◦ module Foo (hoge, var) where
◎   test1/Nums.hs
      module Nums where

     double x = x + x
     quadruple x = double x + double x



◎   test1/Main.hs
      import Nums

     double2    = Nums.double 2
     quadruple4 = Nums.quadruple 4
◎   test1/Nums.hs
      module Nums (double) where

     double x = x + x
     quadruple x = double x + double x



◎   test1/Main.hs
      import Nums

     double2    = Nums.double 2      -- OK
     quadruple4 = Nums.quadruple 4   -- コンパイルエラー
◎   モジュールは階層構造を持つことが可能

◎   階層構造は「A.B.C」のようにドット「.」で表す

◎   A.B.Cというモジュール名にした場合は、
    A/B/C.hsというファイル構成にする
◎   test1/Figure/Sphere.hs
      module Figure.Sphere where
      Area radius = 4 * pi * (radius ^ 2)

◎   test1/Figure/Rectangle.hs
      module Figure.Rectangle where
      Area width height = width * height

◎   test1/Main.hs
      import qualified Figure.Sphere as Sphere
      import qualified Figure.Rectangle as Rect

     sphereArea = Sphere.Area
     rectArea   = Rect.Area
◎   インポート, エクスポートはどちらも範囲を限定できる

◎   標準モジュールを調べる, 使う, 理解するサイクルを
    身につけたい

◎   「こんなのないかな?」と思ったらHoogleとかで探す

◎   モジュールのエクスポートを気にしてきれいなコードを
    書きたいですね

More Related Content

KEY
PPTX
データとは何か
PDF
すごいHaskell楽しく学ぼう-第12章モノイド-
PDF
すごいH 第12章モノイド
KEY
モナドがいっぱい!
PDF
Ekmett勉強会発表資料
ODP
Ekmett勉強会発表資料
PDF
C++コミュニティーの中心でC++をDISる
データとは何か
すごいHaskell楽しく学ぼう-第12章モノイド-
すごいH 第12章モノイド
モナドがいっぱい!
Ekmett勉強会発表資料
Ekmett勉強会発表資料
C++コミュニティーの中心でC++をDISる

What's hot (20)

PDF
関数型プログラミング入門 with OCaml
PDF
関数プログラミング入門
ODP
Real World OCamlを読んでLispと協調してみた
PDF
brainfuckを吐く自作言語bf-reusable
ODP
(define)なしで再帰関数を定義する
PDF
C++のライブラリを簡単に眺めてみよう
PDF
これから Haskell を書くにあたって
PPTX
for関数を使った繰り返し処理によるヒストグラムの一括出力
PDF
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
PDF
関数の最小値を求めることから機械学習へ
PDF
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
PDF
実用Brainf*ckプログラミング
PDF
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
PDF
PDF
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
PDF
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
PDF
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
PDF
Emcjp item21
PDF
Introduction to Categorical Programming (Revised)
PPT
CLR/H No.35-2
関数型プログラミング入門 with OCaml
関数プログラミング入門
Real World OCamlを読んでLispと協調してみた
brainfuckを吐く自作言語bf-reusable
(define)なしで再帰関数を定義する
C++のライブラリを簡単に眺めてみよう
これから Haskell を書くにあたって
for関数を使った繰り返し処理によるヒストグラムの一括出力
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
関数の最小値を求めることから機械学習へ
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
実用Brainf*ckプログラミング
2011.7.3 札幌C++勉強会#2「C++のマクロはどこまで関数をいじれるのか」
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30)
Emcjp item21
Introduction to Categorical Programming (Revised)
CLR/H No.35-2
Ad

Viewers also liked (20)

PDF
第4章 自動比較
PDF
WooCommerce & Apple TV
PDF
20120830 DBリファクタリング読書会第三回
PDF
Tapl 5
PDF
システムテスト自動化標準ガイド第7章
PDF
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
PDF
テスト自動化読書会 第3章 20150523
PPTX
システムテスト自動化標準ガイド 5章発表資料
KEY
文芸的プログラミング
PPTX
[デブサミ2015] スクラムならうまくいく? 〜グリーのネイティブゲーム作りの歴史をひもとく、 そして未来へ〜
PDF
LeanCustomerDevelopment
PPTX
20150418 システムテスト自動化 第二章
PDF
TAPL勉強会 第1章 (2012-07-17)
PDF
NaITE#15オープニング資料
PDF
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
PPTX
システムテスト自動化標準ガイド 読書会 第8章
PDF
名前付けのすすめ / GMOペパボ株式会社 鹿島恵実(かしめぐ)
PDF
要注意!?効果の出ない技術研修に共通する3つのこと
PDF
不確実性への挑戦Ver0.1
PPTX
JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている
第4章 自動比較
WooCommerce & Apple TV
20120830 DBリファクタリング読書会第三回
Tapl 5
システムテスト自動化標準ガイド第7章
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
テスト自動化読書会 第3章 20150523
システムテスト自動化標準ガイド 5章発表資料
文芸的プログラミング
[デブサミ2015] スクラムならうまくいく? 〜グリーのネイティブゲーム作りの歴史をひもとく、 そして未来へ〜
LeanCustomerDevelopment
20150418 システムテスト自動化 第二章
TAPL勉強会 第1章 (2012-07-17)
NaITE#15オープニング資料
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
システムテスト自動化標準ガイド 読書会 第8章
名前付けのすすめ / GMOペパボ株式会社 鹿島恵実(かしめぐ)
要注意!?効果の出ない技術研修に共通する3つのこと
不確実性への挑戦Ver0.1
JJUG CCC 2016 fall バイトコードが君のトモダチになりたがっている
Ad

Similar to すごいHaskell楽しく学ぼう 第6章 (20)

PPTX
競技プログラミングのためのC++入門
PDF
Pythonで始めるDropboxAPI
PDF
20141128 iOSチーム勉強会 My Sweet Swift
PDF
マスターオブゴールーチンアンドチャネル スタートGo #1
PDF
F#入門 ~関数プログラミングとは何か~
PPTX
Boost jp9 program_options
PDF
Common LispでGPGPU
PDF
Adding simpl GVN path into GHC
PDF
20170923 excelユーザーのためのr入門
PPTX
Python opt
KEY
Aizu lt tokyo_luxion
PDF
EmacsとGlossでお絵描きしてみるよ
PDF
Haskell勉強会 14.1〜14.3 の説明資料
KEY
Algebraic DP: 動的計画法を書きやすく
PDF
Pfi Seminar 2010 1 7
PDF
Boost.B-tree introduction
PDF
C++11概要 ライブラリ編
PDF
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
PDF
Implicit Explicit Scala
PDF
HalideでつくるDomain Specific Architectureの世界
競技プログラミングのためのC++入門
Pythonで始めるDropboxAPI
20141128 iOSチーム勉強会 My Sweet Swift
マスターオブゴールーチンアンドチャネル スタートGo #1
F#入門 ~関数プログラミングとは何か~
Boost jp9 program_options
Common LispでGPGPU
Adding simpl GVN path into GHC
20170923 excelユーザーのためのr入門
Python opt
Aizu lt tokyo_luxion
EmacsとGlossでお絵描きしてみるよ
Haskell勉強会 14.1〜14.3 の説明資料
Algebraic DP: 動的計画法を書きやすく
Pfi Seminar 2010 1 7
Boost.B-tree introduction
C++11概要 ライブラリ編
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
Implicit Explicit Scala
HalideでつくるDomain Specific Architectureの世界

More from aomori ringo (7)

PDF
Distributed Systems 第10章 Distributed Object-Based Systems (後編)
PDF
Mathematicaでgolf
PDF
Mathematicaをはじめよう
PPTX
Distributed Systems 第10章 Distributed Object-Based Systems
PPTX
Distributed Systems 第1章 Introduction
PDF
Source monitorと複雑度のはなし
PPTX
md5のアルゴリズム
Distributed Systems 第10章 Distributed Object-Based Systems (後編)
Mathematicaでgolf
Mathematicaをはじめよう
Distributed Systems 第10章 Distributed Object-Based Systems
Distributed Systems 第1章 Introduction
Source monitorと複雑度のはなし
md5のアルゴリズム

すごいHaskell楽しく学ぼう 第6章

  • 2. 1986-2005 ◎ Twitter: @aomoriringo ◎ 最近使ってる言語 ◦ C# ◎ 趣味 2005-2011 ◦ Mathematica 2011- ◎ Haskell歴 ◦ 2ヶ月未満
  • 3. いくつかの関数や型、型クラスなどを定義したファイル ◎ Haskellのプログラムはモジュールの集合 ◎ コードをモジュールに分割するとしあわせ ◦ 再利用性を高める ◦ 管理・修正しやすくする
  • 4. モジュールをインポートする ◎ 標準モジュールを使ってみる ◦ 標準モジュールでいろいろ作ってみる ◦ foldl, foldl’ ◦ 連想リスト ◎ 自分でモジュールを作ってみる
  • 6. 全てをインポート import Data.List ◎ nub, sortのみをインポート import Data.List (nub, sort) ◎ nub以外の全てをインポート import Data.List hiding (nub)
  • 7. import qualified Data.Map ◦ Data.Map.filterのように参照 import qualified Data.Map as M ◦ M.filterのように参照
  • 8. module Fooにhogeとbarがあるとき 宣言 インポートされるもの 参照の方法 import Foo hoge, bar hoge, bar Foo.hoge, Foo.bar import Foo () (なし) import Foo (hoge) hoge hoge, Foo.hoge import Foo hiding (hoge) bar bar, Foo.bar import qualified Foo hoge, bar Foo.hoge, Foo.bar import Foo as F hoge, bar hoge, bar F.hoge, F.bar import qualified Foo as F hoge, bar F.hoge, F.bar
  • 9. Data.Listをインポート ghci> :m + Data.List ghci> :m + Data.List Data.Map Data.Set ◎ Data.Listのインポートを解除 ghci> :m – Data.List ◎ importも使用可能 ghci> import Data.List (nub, sort) ghci> import qualified Data.Map as M hiding (foldl)
  • 10. 標準モジュールを使ってみる Data.List Data.Char Data.Map
  • 11. Hackage ◦ hackage.haskell.org/packages/hackage.html ◎ Hoogle ◦ http://www.haskell.org/hoogle/ ◦ 標準モジュールのソースコードが見れます ◎ Hayoo! ◦ http://holumbus.fh-wedel.de/hayoo/hayoo.html
  • 12. 単語の個数を調べる ghci> :t wordNums wordNums :: String -> [(String,Int)] ghci> wordNums "a haskell learn haskell a a learn good" [("a",3),("good",1),("haskell",2),("learn",2)]
  • 13. 文字列を空白で区切られた文字列のリストに変換する ghci> :t words words :: String -> [String] ghci> words “hey these are the words” [“hey”, “these”, “are”, “the”, “words”] ghci> words “hey these are the words” [“hey”, “these”, “are”, “the”, “words”]
  • 14. リストの同じ要素をグループ化する ghci> :t group group :: Eq a => [a] -> [[a]] ghci> group [1,1,1,2,2,2,3,3,2,2,5,7] [[1,1,1],[2,2,2],[3,3],[2,2],[5],[7]] ghci> group [“hoge”, “var”, “var”, “hoge”, “hoge”] [[“hoge”], [“var”, “var”], [“hoge”, “hoge”]]
  • 15. リストを昇順に並べ替える ghci> :t sort sort :: Ord a => [a] -> [a] ghci> sort [5,4,3,7,2,1] [1,2,3,4,5,7] ghci> sort [“hoge”, “var”, “var”, “hoge”, “hoge”] [“hoge”, “hoge”, “hoge”, “var”, “var”]
  • 16. 文字列を単語に区切って (words) →ソートして (sort) →グループ化して (group) →グループごとに数を数えれば できそうですね!
  • 17. wordNumsの定義 wordNums :: String -> [(String,Int)] wordNums = map (¥ws -> (head ws, length ws)) . group . sort . words ghci> wordNums “a b c b c” [("a",1),(“b",2),(“c",2)] ghci> wordNums “” []
  • 18. あるリストが別のリストに含まれるかどうかを調べる ghci> :t isIn isIn :: [a] -> [a] -> Bool ghci> “art” `isIn` “party” True ghci> [1,2] `isIn` [1,3,5] False
  • 19. リストに対してtailを繰り返し適用する ghci> :t tails tails :: [a] -> [[a]] ghci> tails “party” [“party”, “arty”, “rty”, “ty”, “y”, “”] ghci> tails [1,2,3] [[1,2,3], [2,3], [3], []]
  • 20. 2つ目のリストが1つ目のリストで 始まっているかどうかを返す ghci> :t isPrefixOf isPrefixOf :: String -> String -> Bool ghci> “hawaii” `isPrefixOf` “hawaii joe” True ghci> “haha” `isPrefixOf` “ha” False ghci> “ha” `isPrefixOf` “haha” True
  • 21. “art” `isPrefixOf` “party” -- False “art” `isPrefixOf` “arty” -- True “art” `isPrefixOf` “rty” -- False “art” `isPrefixOf` “ty” -- False “art” `isPrefixOf` “y” -- False
  • 22. リストのうち、述語を満たすものがあるかどうかを返す ghci> :t any any :: (a -> Bool) -> [a] -> Bool ghci> any (>4) [1,2,3] False ghci> any id [False, False, True] True
  • 23. isInの定義 isIn :: (Eq a) => [a] -> [a] -> Bool needle `isIn` haystack = any (needle `isPrefixOf`) (tails haystack) needle: 針。見つけたいリスト haystack: 干し草の山。検索対象のリスト
  • 24. Data.List.isPrefixOf ◦ 前方一致 ◦ さっき使った ◎ Data.List.isSuffixOf ◦ 後方一致 ◎ Data.List.isInfixOf ◦ 中間一致 ◦ さっき作った(isIn)
  • 25. シーザー暗号 ◦ 平文の各文字を辞書順にn文字シフトして作る
  • 26. 文字<->Unicode変換 ghci> :t ord ord :: Char -> Int ghci> ord ‘a’ 97 ghci> :t chr chr :: Int -> Char ghci> chr 97 ‘a’ ghci> map ord “abcdefgh” [97,98,99,100,101,102,103,104]
  • 27. 指定した文字数分シフトする encode :: Int -> String -> String encode offset msg = map (¥c -> chr $ ord c + offset) msg ◎ 指定した文字数分逆にシフトする decode :: Int -> String -> String decode shift msg = encode (negate shift) msg
  • 28. ghci> encode 3 “hey mark” “kh|#pdun” ghci> decode 3 “kh|#pdun” “hey mark” ghci> decode 3 $ encode 3 “abc” “abc”
  • 29. 各桁の数の合計がnになる最初の自然数をみつける ghci> :t firstTo firstTo :: Int -> Int ghci> firstTo 1 1 ghci> firstTo 13 49
  • 30. 文字を数に変換する ghci> :t digitToInt digitToInt :: Char -> Int ghci> digitToInt ‘2’ 2 ghci> digitToInt ‘F’ 15 ghci> digitToInt ‘z’ *** Exception: Char.digitToInt: not a digit 'z'
  • 31. 各桁の数の和を返す digitSum :: Int -> Int digitSum = sum . map digitToInt . show ghci> digitSum 30 3 ghci> digitSum 1234 10
  • 32. ghci> :t find find :: (a -> Bool) -> [a] -> Maybe a ghci> find (>4) [3,4,5,6,7] Nothing | Just a Just 5 ghci> find odd [2,4,6,8,9] Just 9 ghci> find (==‘z’) “haskell” Nothing
  • 33. firstToの定義 firstTo :: Int -> Maybe Int firstTo n = find (¥x -> digitSum x == n) [1..] ghci> firstTo 27 Just 999 ghci> firstTo 40 Just 49999
  • 35. ghci> foldl (+) 0 [1..2000000] 2000001000000 ◦ 遅い ◦ サイズ、環境によってはスタックオーバーフロー ghci> Data.List.foldl’ (+) 0 [1..2000000] 2000001000000 ◦ foldlより速い ◦ オーバーフローしない
  • 36. foldl (+) 0 [1,2,3] = foldl (+) (0 + 1) [2,3] = foldl (+) ((0 + 1) + 2) [3] = foldl (+) (((0 + 1) + 2) + 3) [] = ((0 + 1) + 2) + 3 = (1 + 2) + 3 = 3 + 3 = 6
  • 37. 正格な(遅延でない)左畳み込み foldl’ (+) 0 [1,2,3] = foldl’ (+) 1 [2,3] = foldl’ (+) 3 [3] = foldl’ (+) 6 [] = 6
  • 39. 添字として任意の型を使用する配列 ◎ 呼び方はいろいろ ◦ Map ◦ Dictionary ◦ Hash
  • 40. タプルを連想リストっぽく扱う ghci> :t lookup lookup :: Eq a => a -> [(a,b)] -> Maybe b ghci> lookup “b” [(“a”,1), (“b”,2), (“c”,3)] Just 2 ghci> lookup “k” [(“a”,1), (“b”,2), (“c”,3)] Nothing
  • 41. 連想リスト(Map)のモジュール ◦ Data.Map.lookup ◦ Data.Map.insert ◦ Data.Map.delete ◦ Data.Map.size ◦ etc..
  • 42. ◎ Data.Mapで連想リストを表す型 ◎ keyとvalueの型を持つ ghci> let m = Data.Map.fromList [(“foo”,1), (“bar”,2)] ghci> :t m m :: Data.Map.Map [Char] Integer ghci> let m2 = Data.Map.fromList [(‘a’, True), (‘b’, False)] ghci> :t m2 m2 :: Data.Map.Map Char Bool
  • 43. ghci> import qualified Data.Map as Map ◎ keyで検索する ghci> let m = Map.fromList [(“a”,1), (“b”,2)] ghci> Map.lookup “b” m Just 2 ghci> Map.lookup “c” m Nothing ◎ key=“c”, value=3の要素を挿入する ghci> let m2 = Map.insert “c” 3 m ghci> Map.lookup “c” m2 Just 3 ghci> Map.size m2 3
  • 44. valueに関数を適用して新しいMapを作る ghci> m2 fromList [("a",1),("b",2),("c",3)] ghci> Map.map (^2) m2 fromList [("a",1),("b",4),("c",9)] ghci> Map.map show m2 fromList [(“a”,”1”), (“b”,”2”), (“c”, “3”)]
  • 45. keyが重複した際の振る舞いを決める ghci> Map.fromList [(1,2),(1,50),(1,10),(2,3)] fromList [(1,10),(2,3)] ghci> Map.fromListWith (+) [(1,2),(1,50),(1,10),(2,3)] fromList [(1,62),(2,3)] ghci> Map.fromListWith max [(1,2),(1,50),(1,10),(2,3)] fromList [(1,50),(2,3)]
  • 47. 先頭にモジュール宣言を書く -- Foo.hs module Foo where ◦ モジュール名とファイル名は同じにしなければならない ◎ モジュールの中身を ◦ 全て公開したい(エクスポート) module Foo where ◦ 一部だけ公開したい ◦ module Foo (hoge, var) where
  • 48. test1/Nums.hs module Nums where double x = x + x quadruple x = double x + double x ◎ test1/Main.hs import Nums double2 = Nums.double 2 quadruple4 = Nums.quadruple 4
  • 49. test1/Nums.hs module Nums (double) where double x = x + x quadruple x = double x + double x ◎ test1/Main.hs import Nums double2 = Nums.double 2 -- OK quadruple4 = Nums.quadruple 4 -- コンパイルエラー
  • 50. モジュールは階層構造を持つことが可能 ◎ 階層構造は「A.B.C」のようにドット「.」で表す ◎ A.B.Cというモジュール名にした場合は、 A/B/C.hsというファイル構成にする
  • 51. test1/Figure/Sphere.hs module Figure.Sphere where Area radius = 4 * pi * (radius ^ 2) ◎ test1/Figure/Rectangle.hs module Figure.Rectangle where Area width height = width * height ◎ test1/Main.hs import qualified Figure.Sphere as Sphere import qualified Figure.Rectangle as Rect sphereArea = Sphere.Area rectArea = Rect.Area
  • 52. インポート, エクスポートはどちらも範囲を限定できる ◎ 標準モジュールを調べる, 使う, 理解するサイクルを 身につけたい ◎ 「こんなのないかな?」と思ったらHoogleとかで探す ◎ モジュールのエクスポートを気にしてきれいなコードを 書きたいですね