ふつうのHaskellプログラミング 第3章 -2
ふつうのHaskellプログラミング
ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
- 作者: 青木峰郎,山下伸夫
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2014/10/05
- メディア: オンデマンド (ペーパーバック)
- この商品を含むブログを見る
噂のすごいH本を読んで楽しくHaskellを学んでいこうというコンセプト
会社のHaskellerさんに
「関数型素人がすごいH本で入門すると中盤で詰むよ」
「初めてならふつうのH本からがおすすめ」
ということなので『ふつうのHaskellプログラミング』からやっていこうかと。
第3章 Haskellの基礎(2)型と高階関数 - 2
# expand1.hs main = do cs <- getContents putStr $ expand cs expand :: String -> String expand cs = concat $ map expandTab cs expandTab :: Char -> String expandTab c = if c == '\t' then " " else [c]
このサンプルコードを使うとHlintの警告で
Warning: Use concatMap. Found: concat $ map expandTab cs Why not: concatMap expandTab cs
main = do cs <- getContents putStr $ expand cs expand :: String -> String expand = concatMap expandTab expandTab :: Char -> String expandTab c = if c == '\t' then " " else [c]
これで警告がなくなる
concatMapの型宣言は以下
concatMap :: (a -> [b]) -> [a] -> [b] concat :: [[a]] -> [a] map :: (a -> b) -> [a] -> [b]
mapでリスト化したものをconcatするのがconcatMap
まんまだね。
-- Hoogleの説明 concatMap :: Foldable t => (a -> [b]) -> t a -> [b] base Prelude Map a function over all the elements of a container and concatenate the resulting lists.
Hoogleすげー便利だけど英語が...覚えるしかないか。
Foldableは束縛可能?束縛した関数って意味かな?=>
これの書き方はまだ知らん。
Mapで生成したリストをconcatenateするって言ってるけどconcatenateって言うんスネ〜
パターンマッチ
要はif文の後にelsif
とかelse if
とか使って条件を繋げてかく方法。
普段からif ~~
を何個か使って条件書いてたけど汚く感じてた。
Haskellは結構キレイに書けるんだなぁ。
関数名 第一引数のパターン 第二引数のパターン ... = 定義1 関数名 第一引数のパターン 第二引数のパターン ... = 定義2 関数名 第一引数のパターン 第二引数のパターン ... = 定義3 ... ... ...
expandTab :: Char -> String expandTab '\t' = replicate tabStop ' ' expandTab c = [c]
こんな感じに
'\t'
ならこれ、
c
ならこれ。
c
に意味はないのかな?Charのc
ではあるけど。
\t
以外は全てc
にいく。
ちなみにconcatMap
はここで説明があった。
eta reduce
はまだ説明ないけど、これは新しい概念なのかな?ちゃんと調べたら書く。
map
関数の定義
map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs
リストに対するパターンマッチと関数の再帰定義と言う概念
リストに対するパターンマッチ
map f [] = []
これは空リストの時の処理、見たまんま。
map f (x:xs) = f x : map f xs
(x:xs)
がリストのパターン
最初の要素をx
に束縛して、他をxsに束縛する。(束縛の言い方はあっているのかな?)
そしてxs
にmap
を適応する。
関数の再帰定義
map f (x:xs) = f x : map f (x:xs) = f x : map f xs ...
こんな感じで繋がっている
先頭を処理しつつ、後続はまた再帰で処理している。
この考え方は書いて覚えるしかないかな。こう言う関数の組み立てはしないからなぁ。
余談
文字列は基本的にCharのリストと言う意識は再認識しないと。
練習問題のaとAを入れ替えるswapa.hs
main = do cs <- getContents putStr $ map swapa cs swapa :: Char -> Char swapa 'a' = 'A' swapa 'A' = 'a' swapa c = c
cs
はString
だけどmap
関数はそのCharリストを一つ一つ再帰して処理をするから
この場合swapa
はChar -> Char
の型になるのは慣れないな〜
今日は以上
ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
- 作者: 青木峰郎,山下伸夫
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2014/10/05
- メディア: オンデマンド (ペーパーバック)
- この商品を含むブログを見る