北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

今日は「Haskell入門ハンズオン!」の日です

今日は「Haskell入門ハンズオン!」の日です

https://shinjukuhs.connpass.com/event/58224/へメンター枠で来ていますので、自分用のメモを残しておく。

はじめに / 木下さん

  • #Haskel
  • 講師重城さん+メンター5人居ます
  • haskellでわからないことはteratailで質問しましょう
  • 8/28 に Haskell入門者LT大会やるよ

Haskellの概要 / 重城さん

  • 自己紹介 : Gentoo on KVM on Gentoo, TUT-code, Xmonad, rxvt-unicode, Tmux, Mutt, HHKB
  • ハンズオンの中身 : 完全入門者向けだけど、Haskellの面白さは伝えたい
  • stack --version stack ghci :quit
  • 4492 'c' pi 電卓的な使い方、 it
  • カーソルキーで履歴を辿れる
  • repeat "Haskell" からの Ctrl+C
  • サンプルコード
  • pwdcdディレクトリ移動して、 stack ghci
  • 行儀が悪いのでTABを8文字幅で使うよ!(本当は4スペースが行儀がいい)
  • myFavoriteFruit = "apple":load で読み込み
  • "banana" に変更してmyFavoriteFruit` をしても変わらない
  • :reload すると切り替わる
  • double x = x * 2 関数
  • (\x -> x * 2) 8 関数リテラル
  • 演算子と関数は同じ
  • 演算子は中置で記号列。 () で関数になる
  • 関数は `` でe演算子になる
  • lucky :: Integer 型宣言
  • Maybe Just Nothing
  • タプル taro = ("Taro Yamada", 35)
  • パターンマッチ
    • helloTo (Just n) = "Hello, " ++ n ++ "!"
    • helloTo Nothing = "Hello, customer!"
    • human (n, a) = n ++ "(" ++ show a ++ ")"
    • リテラル safeRecip 0 = Nothing
    • ワイルドカード isNothing (Just _) = False
    • アズパターン atPattern jx@(Just x) = show jx ++ ": " ++ show x
  • "" は文字列、 '' は文字
  • パターンが抜けているときは部分関数になる。マッチしないと例外
  • 例外はI/Oモナドで拾える
  • 「代入じゃなくて束縛と言わないと怒られる」
  • show は多相関数なので Maybe Integer にも Integer にも使える
  • ガード safeSqrt x | x < 0 = Nothing
  • case式 yesNo c = case c of 'n' -> Just False
  • 多相: ignoreSecond :: a -> b -> a ignoreSecond x y = x
  • 型シノニム: type Human = (String, Integer)
  • モジュールの導入 import Data.Maybe (fromMaybe)

ここで休憩。

  • 多相関数を使うと、ソースコードがきれいになる
  • const の2つの側面
    • 第二引数を無視する関数
    • 常に定数を返す関数 (const 関数への部分適用)
    • ignoreSecond と同じ定義
  • 関数適用演算子 $
    • f x なので必要ない
    • ($) f x
    • recipe $ 3 + 5 カッコが取れる
  • 部分適用
    • bmi h w = w / (h / 100) ^ 2
    • bmiTaro' = bmi 170 2つある引数のうちひとつだけを与えた
    • (125 /) 第一引数に対する部分適用
    • (/ 5) 第二引数に対する部分適用
  • 関数合成 : (* 2) . (+ 3)
    • 関数は後ろから適用される
  • 繰り返し
    • 再帰よりリストは簡単
    • sumN n = sum [1 .. n]
    • 3の倍数以外の総和 filter ((/= 0) . (`mod` 3))
    • 5で割ったあまりの総和 map (`mod` 5)
  • モンテカルロ法の例
    • 正方形内の点を列挙、円に入るもののみをろ過、残った点を数える
  • 無限リスト take 10 [1 ..]
    • 必要になるまで評価しないので、無限時間はかからない
    • 処理と終了条件を分離できる
  • リストへの追加 5 : [3, 2, 9]
  • 空リスト []
  • パターンマッチ headTail (x : xs)
  • 2段のリストを1段に concat [[1,2,3], [4,5], [6,7]]
  • すべての組み合わせで concatMap
    • (`concatMap` [1, 2, 3]) $ \x -> (`concatMap` [4, 5, 6]) $ \y -> (`concatMap` [7, 8]) $ \z -> [x * y * z]
  • 糖衣構文 リスト内包表記 [x * y * z | x <- [1,2,3], y <- [4, 5, 6], z <- [7, 8]]

時間がないので再帰は飛ばすことに。「近現代史は教科書読んでおいてね、と同じ」。

  • Haskell以外の言語では、式の評価と入出力が分けられている
    • 3 + 5 を評価しても、誰かの銀行口座が0円になることはない
  • 評価と実行は分かれている (が、対話環境が隠している)
    • 対話環境は、評価結果が入出力をする「機械」だったときに実行する
  • putStrLn は文字列を引数として取り、それを表示する機械を返す
  • getLine IO String 機械が出した結果を対話環境が表示
  • 値を機械から機械へ渡す >>=
  • getLine >>= \x -> で改行をして書くとわかりやすい
  • 糖衣構文 do 記法
    • >>=>> を隠している
  • 実行可能ファイルを作る stack ghc -- *.hs
    • TAB使いなので -fno-warn-tabs
  • 標準入力からの入力を変換するプログラムの書き方
    • interact
    • 3回 love というと I love you しか返ってこなくなる例

ここからは各自でハンズオン。