Haskellはおもしろい
http://readhbon.doorkeeper.jp/events/16706
Haskellは変な言語
IRCチャンネルがある
Haskellは純粋関数型言語
コンピュータにナニをするかは伝えず、なんであるかを伝える=関数
- 束縛(一度定義した変数の値を変更は出来ない)
- 遅延評価
- 副作用がない
- リストは要求があったときに一度だけ走査される
- Haskellは静的型づけ言語
- コンパイラがエラーをチェックする
- 型推論
あと、Haskellは簡潔にコードを書くことが出来る
Haskellの世界に飛び込むのに必要なもの
コンパイラはGHC 対話モードつき
話の空中戦はつらいよ
第1章 はじめの第一歩
ghciを起動してみる
➜ ~ ghci GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :set prompt "ghci> " ghci>
軽い演算
ghci> 2 + 5 7 ghci> 49 * 100 4900 ghci> 1892 - 1472 420 ghci> 5 / 2 2.5 ghci> (50 * 100) - 4999 1 ghci> 50 * 100 - 4999 1 ghci> 50 * (100 - 4999) -244950
ghci> 5 * -3 <interactive>:10:1: Precedence parsing error cannot mix `*' [infixl 7] and prefix `-' [infixl 6] in the same infix expression ghci> 5 * (-3) -15
ghci> True && False False ghci> True && True True
ghci> "hello" == "hello" True ghci> 5 /= 4 True ghci> 5 /= 5 False
1.1 関数呼び出し
上の例は中置関数。
これからの例は前置関数
ghci> succ 8 9 ghci> min 9 10 9 ghci> min 3.4 3.2 3.2 ghci> min 100 101 100 ghci> max 100 101 101
中置関数と前置関数の組み合わせ
ghci> succ 9 * 10 100 ghci> succ (9 * 10) 91
バッククオートで中置関数
ghci> 92 `div` 10 9
1.2 赤ちゃんの最初の関数
doubleMe x = x + x
doubleMe x = x + x main = do print $ doubleMe 2
doubleMe x = x + x doubleUs x y = doubleMe x + doubleMe y main = do print $ doubleUs 4 9
- 明らかに正しい関数を組み合わせて、より大きな関数を組み立てる
- すべての関数はなにかを返さなければならない
- Haskellのifは必ず値を返す式であって、文ではない
1.3 リスト入門
- いちようなデータ構造
- 同じ型の要素を複数個格納できる
- 違う型の要素を格納することはできない
連結
ghci> let lostNumbers = [4,8,15,16,23,42] ghci> lostNumbers [4,8,15,16,23,42]
(文字列は文字のリスト)
- ++は連結
- :はcons演算子で、リストの先頭に何かを追加するヤツ
ghci> "hello " ++ "world" "hello world"
ghci> 5:[6,7,8,9] [5,6,7,8,9]
ghci> [6,7,8,9] ++ 5 -- エラー!!
アクセス
- !!を使う
ghci> "Steve Buscemi" !! 6 'B'
リストの中のリスト
リストのなかにリストを含むことが出来る
リストの比較
リスト同士の比較も可能
ghci> [3,2,1] > [2,1,0] True ghci> [3,2,1] > [4,1,0] False
リスト操作
- head
- tail
- last
- init など
ghci> head [5,4,3,2,1] 5 ghci> tail [5,4,3,2,1] [4,3,2,1] ghci> last [5,4,3,2,1] 1 ghci> init [5,4,3,2,1] [5,4,3,2] ghci> head [] *** Exception: Prelude.head: empty list ghci> length [5,4,3,2,1] 5 ghci> null [5,4,3,2,1] False ghci> reverse [5,4,3,2,1] [1,2,3,4,5] ghci> take 3 [5,4,3,2,1] [5,4,3] ghci> take 1 [5,4,3,2,1] [5] ghci> take 99 [5,4,3,2,1] [5,4,3,2,1] ghci> take 0 [5,4,3,2,1] [] ghci> drop 0 [5,4,3,2,1] [5,4,3,2,1] ghci> drop 3 [5,4,3,2,1] [2,1] ghci> drop 100 [5,4,3,2,1] [] ghci> maximum [5,4,3,2,1] 5 ghci> minimum [5,4,3,2,1] 1 ghci> sum [5,4,3,2,1] 15 ghci> product [5,4,3,2,1] 120 ghci> 4 `elem` [5,4,3,2,1] True ghci> 10 `elem` [5,4,3,2,1] False
1.4 レンジでチン
手入力はだるい→レンジを使おう
ghci> [1..20] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
ghci> ['a'..'z'] "abcdefghijklmnopqrstuvwxyz" ghci> [2,4..20] [2,4,6,8,10,12,14,16,18,20] ghci> [3,4..20] [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] ghci> [3,6..20] [3,6,9,12,15,18]
(でもレンジはそこまで賢くはない)
ghci> take 10 (cycle [1,2,3]) [1,2,3,1,2,3,1,2,3,1]
1.5 リスト内包表記
ghci> [x*2 | x <- [1..10]] [2,4,6,8,10,12,14,16,18,20] ghci> [x*2 | x <- [1..10], x*2 >= 12] [12,14,16,18,20] ghci> [ x*y | x <- [2,5,10], y <- [8,10,11]] [16,20,22,40,50,55,80,100,110]
1.6 タプル
リストとタプルは違う
- 複数の違う型の要素を格納できる
- サイズが固定
2次元ベクトルみたいな使い方がなされる
ghci> (1, 3) (1,3) ghci> (3, 'a', "hello") (3,'a',"hello")
タプルは固定長なので、タプルに要素を追加する関数は用意されていない
サイズ2のタプル ペア用の関数があったりする
ghci> fst (8, 11) 8 ghci> fst ("Wow", False) "Wow" ghci> snd (8, 11) 11 ghci> snd ("Wow", False) False
なお、Haskellは遅延評価なので、有限リストと無限リストをzipすることもできる
直角三角形をみつける
タプルとリスト内包表記を組み合わせることもできる
rightTriangles' = [ (a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2, a+b+c == 24] main = do print $ rightTriangles'
[(8,6,10)]
感想
サンプルコードの実行とメモが追いついていないので、サンプルコードの実行はぼちぼちにして文章を読んだほうが良いかもしれないと感じました。