第1回スタートHaskell2に行ってきました。
聞いてきたこと
「すごいHaskell 楽しく学ぼう」(以下「すごいH本」)の中身は、- イントロダクション: @Lost_dog_ さん
- 第1章:はじめの第一歩: @Lost_dog_ さん
- 第2章:型を信じろ!: @skoji さん
- Haskell に於けるユニットテストの方法: @shokos さん
- Haskell を上手いこと身につける方法: @dekosuke さん
- Yesod を使ったHaskell によるWeb アプリケーション作成の紹介: @seizans さん
聞いてきた事の詳細
- Haskell はlazy(non-strict)
- Haskell は遅延評価する
- Haskell は純粋
- 関数は同じ引数に対して必ず同じ結果を返す
- 変数は無い(再代入してはならない)
- Haskell は静的型付言語
- Haskell は型クラスがある
- オブジェクト指向で言う所のクラスとは関係無い。気をつけろ!!
- 最後のお願いです。……Haskell' のこと、忘れて下さい……
- いつからInt(Float) だと錯覚していた?
- 1 と書いても、この時点ではInt ではなく、Num a (Int なのかFloat なのか、はたまた別の数値的な型なのかがわからない)
- 1.0 と書いても、この時点ではFloat ではなく、Floating a (Float なのかDouble なのかがわからない)
- 明示的に書くか、型推論をしない限り、Haskell は型がわからない!
- Haskell をコンパイルして実行形式にすると、そのバイナリは型データを全部捨て去る
- Haskell に於けるUML 的な存在は型クラス
- デバッグはモジュール単位で分割して行えば良いんじゃない
- Haskell でもユニットテストは出来る
- HUnit で単体テストが普通にできる
- QuickCheck で関数同士を比較して同一の値を返すかどうかチェックできる(?)
- 詳しくはこちら。Haskellテストスライド
- Haskell を上手いこと勉強するには
- Project Euler の問題をガンガン解けば良いんじゃ
- 48時間でSchemeを書こう - Wikibooks をやれば良いんじゃ
- とりあえずパーサ(Html とかの)を書けば良いんじゃ
- Yesod
- Haskell 製Web アプリケーション
- SQL インジェクションがない
- 他にもいろいろセキュリティが強固
- 自リソース内でのリンク切れが起こらない(リンク切れがあるとコンパイル時にエラーが出る)
- コンパイルするから、「実行しないとわからない」という潰すのが難しいエラーをあらかじめ減らしておくことができる
- 詳しくはこちら。20120527yesod
感想
あらかじめすごいH本を一通り読んでから臨んだので、復習と言った体で話を聞く事が出来た為、理解が深まったように思います。(中学・高校時代もこんな感じで授業の予習をしっかりしていれば良かったのに……俺の馬鹿馬鹿!)
独学も結構ですが、やっぱり学習対象を熟知している人から直接教えてもらえる、というのは素晴らしい!
本とにらめっこしてもいまいち理解出来なかった事が、エキスパートに教えを請うことでスッと落ちてくる快感!
今回の勉強会に参加して、Haskell みたいな難解(だと個人的には思っている)な言語は自分以外の誰かから直接教えてもらった方が良いように思いました。
LT に関しては高度な内容も含まれていた(と思います。だよね? 高度だったよね? それとも俺がただ単にノータリンなだけ?)ので、
初心者の僕にはちょっとハードルが高かったですが、面白かったです。Haskell ってこんな事もできるんだ……という印象を受けました。
まだ先の話ですが、僕が何度も、そう何度も挫折した「モナド」や「I/O」の話を聞けるのが楽しみです。
次回も参加したいです!
- 作者: Miran Lipovača,田中英行,村主崇行
- 出版社/メーカー: オーム社
- 発売日: 2012/05/23
- メディア: 単行本(ソフトカバー)
- 購入: 25人 クリック: 580回
- この商品を含むブログ (46件) を見る
[おまけ]僕が現地で考えた、スタートHaskell2 の練習問題の回答
1.
Prelude> 18.6 / 31 - 2.604 / 3.1 - 0.8556 / 0.31
2.
Prelude> ['z', 'v' .. 'b']
3.
Prelude> tail (take 3 aList) ++ [last (init aList)]
4.
Prelude> 1:2:3:4:5:[]
5. 欠番
6.
Prelude> head [x | x <- [1..], x `mod` 2 == 0, x `mod` 3 == 0, x `mod` 4 == 0, x `mod` 5 == 0, x `mod` 6 == 0, x `mod` 7 == 0, x `mod` 8 == 0, x `mod` 9 == 0, x `mod` 10 == 0]なんて醜いコードなんだ……
会場で参加者の方が発表していた
Prelude> head [x | x <- [1..], all(\y -> x `mod` y == 0) [2..10]]というコードの方が明らかにスマートだと思います。
7.
Prelude> head [(a, b, c) | a <- [1 .. 999], b <- [(a + 1)..999], c <- [(b + 1)..999], a + b + c == 1000, a^2 + b^2 == c^2]こちらよりも、現地で@kazu_yamamoto さんが示していた
Prelude> [(a,b,c) | a <- [1..999], b <- [a..998], let c=1000-a-b, a^2 + b^2 == c^2]の方が数倍(数百、数千倍?)高速です。(このlet の使い方はどういう意味なんだろう……)
8.
Prelude> length [y | y <- [show x | x <- [100 .. 999]], head y == last y]
9.
Prelude> length [x | x <- [a * 10000 + b * 1000 + c * 100 + d *10 + e | a <- [1..3], b <- [1..3], c <- [1..3], d <- [1..3], e <- [1..3]], x `mod` 3 == 0]
1.
- null 関数
- 任意の型のリストを受け取ってBool 値を返す関数
- abs 関数
- Num 型クラスに属する変数を受け取って、その型の結果を返す関数
- take 関数
- take :: Int -> [a] -> [a] (Int 型の変数を受け取り、任意の型のリストを受け取って、その型のリストを返す関数)
2.
2-1- 'a'
- 'a' :: Char
- ['a', 'b', 'c']
- ['a', 'b', 'c'] :: [Char]
- ('a', 'b', 'c')
- ('a', 'b', 'c') :: (Char, Char, Char)
- 'a' == 'a'
- 'a' == 'a' :: Bool
- ("Hello", "world!")
- ("Hello", "world!") :: ([Char], [Char])
- 100
- 100 :: Num a => a
- show
- show :: a -> [Char] (←誤り。正しくは show :: Show a => a -> String)
- take 3 [1..]
- take 3 [1..] :: Num a => [a] (←誤り。正しくは (Enum a, Num a) => [a])
- [(False, 'o'), (True, '1')]
- [(False, 'o'), (True, '1')] :: [(Bool, Char)]
- ([False, True], ['0', '1'])
- ([False, True], ['0', '1']) :: ([Bool], [Char])
- [init , tail , reverse]
- [init , tail , reverse] :: [ [a] -> [a] ]
- second xs = head (tail xs)
- second :: [a] -> a
- swap (x, y) = (y, x)
- swap :: (a, b) -> (b, a) (←正しくは swap :: (t1, t) -> (t, t1))
- pair x y = (x, y)
- pair :: a -> b -> (a, b) (←正しくは pair :: t -> t1 -> (t, t1))
- double x = x * 2
- double :: Num a => a -> a
- palindrome xs = reverse xs == xs
- palindrome :: Eq a => [a] -> Bool
- twice f x = f (f x)
- twice :: (a -> a) -> a -> a (←正しくは twice :: (t -> t) -> t -> t)
3.
(*) は Num a => a -> a -> a(/) は Fractional a => a -> a -> a
型クラスが異なるので、両式は異なる。
4.
型だけから想像するの難しくないですか……? 慣れれば分かるようになるんでしょうか。と言うわけでHoogle で検索書けた奴を貼るという暴挙に。
5.
pred6.
Prelude> [(42, last)] [(42, last)] :: Num t => [(t, [a] -> a)]
7.
1."hoge" :: [Char] 2.let foo = 1 :: Integer :t foo foo :: Integer 3.let bar = [12.3, 23.4] :t bar bar :: [Double] 4.? 5.id 3 6.replicate 3 2 7.? |8.
Eq: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#t:EqEq とShow 両方に属する型: Char とか
9.
Prelude> maxBound :: Int 2147483647
10.
pi はFloating a => a だから、Int と演算させようとするとエラーになる11.
Prelude> (1 :: Int) + (1.0 :: Double) は、Int とDouble を混ぜて演算しているからエラーになる。Prelude> 1 + 1.0 は、Haskell 側で型推論してくれるからエラーが起きない。(1と1.0 が両方ともFractionalとして解釈されるはず……)
12.
Prelude> fromIntegral(1 :: Int) + (1.0 :: Double)これで良いんでしょうか? 問題の意図が若干読み取れませんでした。
13.
N = a 'div' length xs where a = 10 xs = [1, 2, 3, 4, 5]↓
largeN = a `div` length xs where a = 10 xs = [1, 2, 3, 4, 5]
- 関数名の先頭は小文字から始まらなければならない
- 関数を中置関数として扱う場合は、シングルクォートではなくバッククォートで括らなければならな
- where 節以下のインデンテーションは同じ深さでなければならない