単なる読書メモ
無名関数
書き方
\n -> n * n
使い方
map (\n -> n * n) [1,2,3,4]
関数合成
書き方
before
lineCount:: String -> Int lineCount s = length $ lines s
after
lineCount:: String -> Int lineCount = length . lines
部分適用
例:5の倍数を得る関数
二つの引数をとって掛け算をする関数を部分適用するパターン
-- 二つの引数をとって掛け算をする関数 multiply:: Int -> Int -> Int multiply x y = x * y -- 5の倍数を得る関数 multiplyWith5:: Int -> Int multiplyWith5 = multiply 5
セクションを使ったパターン
multiplyWith5:: Int -> Int multiplyWith5 = (* 5)
変数を削減する
例:[String]
に添字を加える
before
zipWithIndex:: [String] -> [(Int, String)] zipWithIndex xs = zip [1..] xs
intermediate
zipWithIndex:: [String] -> [(Int, String)] zipWithIndex xs = f xs where f = zip [1..]
after
zipWithIndex:: [String] -> [(Int, String)] zipWithIndex = zip [1..]
関数合成と部分適用でリファクタリング
before
import System.Environment import Data.List -- main main = do as <- getArgs cs <- getContents putStr $ fgrep (head as) cs -- grep fgrep:: String -> String -> String fgrep ptn s = unlines $ filter match $ lines s where match:: String -> Bool match line = any prefixp $ tails line prefixp:: String -> Bool prefixp line = ptn `isPrefixOf` line
step1
prefixp
を部分適用(セクション)で書き直し
prefixp:: String -> Bool prefixp = (isPrefixOf ptn)
step2
match
にprefixp
を組み込む
match:: String -> Bool match line = any (isPrefixOf ptn) $ tails line
step3
match
の引数を省略
match:: String -> Bool match = any (isPrefixOf ptn) . tails
step4
fgrep
の$
を消す
fgrep:: String -> String -> String fgrep ptn = unlines . filter match . lines where match:: String -> Bool match = any (isPrefixOf ptn) . tails
step5
match
を独立させる
match:: String -> String -> Bool match ptn = any (isPrefixOf ptn) . tails
step6
fgrep
のwhere
をなくす
fgrep ptn = unlines . filter (match ptn) . lines
after
import System.Environment import Data.List -- main main = do as <- getArgs cs <- getContents putStr $ fgrep (head as) cs -- grep fgrep:: String -> String -> String fgrep ptn = unlines . filter (match ptn) . lines -- match match:: String -> String -> Bool match ptn = any (isPrefixOf ptn) . tails