to2yの日記

 | 

2006-07-29ふつける勉強会 第七回目 第七章 「関数」

値としての関数

関数束縛

square n = n * n

は「引数nを2乗」する関数を、square変数に束縛する

squareは関数を値として持つ変数

高階関数

関数引数にとる、もしくは返り値とする関数のこと

無名関数

\num -> num * num

schemeでは

(lambda (num) num * num) 'だっけ?

2引数の場合

\x y -> x + y

無名関数でのパターンマッチ

\(x,y) -> x + y

のように無名関数の定義でパターンマッチが使える

ただし、定義できるパターンは1つだけ

関数合成

関数合成::複数の関数を合成して、新しい関数を作ること

(.)関数

(.)::(b -> c) -> (a -> b) -> (a -> c)

1引数のときはこんな感じて定義すればよい?

. f g = \a -> f $ g a


numberOfLinesの例

lines::String -> [String]

length::[a] -> Int

なので、

(length . lines) :: String -> Int

(length.lines)のように空白あけなくても大丈夫(少なくともGHCiでは)

(length . lines) "a" ==> 1

length . lines "a" ==> lines "a"が先に結合してしまうためエラー

(.)は右結合

sortLines::String -> String

sortLines = unlines . (sort . lines)

sortLines = unlines . sort . lines

としても同じ意味

部分適用

関数の一部の引数適用した関数を作ること

map (+ 1) -- 部分適用の例

Haskellでの関数適用

map (+ 1) [1,2,3]

(map (+ 1)) [1,2,3]

部分適用として解釈される

セクション

二項演算子に対して引数を1つだけ渡した関数のこと

ポイントフリースタイル

(.)関数部分適用を使って関数関数で定義するスタイルのこと

zipLineNumber xs = zip [1..] xs

zipLineNumber = zip [1..]

練習問題

1,2,3

import Char
lstrip ::[Char] -> [Char]
lstrip = dropWhile isSpace

rstrip ::[Char] -> [Char]
rstrip = reverse . lstrip . reverse

strip ::[Char] -> [Char]
strip = rstrip . lstrip

4

main = do cs <- getContents
          putStr $ lastNLines 5 cs

lastNLines n = unlines . takeLast n . lines 
takeLast n = reverse . take n . reverse 

以下はポイントフリーと呼ぶのか

takeLast = \n -> reverse . take n . reverse

5

import System
import List

main = do cs <- getContents
          args <- getArgs
          putStr $ fgrep (head args) cs

fgrep :: String -> String -> String
fgrep pattern = unlines . filter match . lines
 where
     match :: String -> Bool
     match = any (isPrefixOf pattern) . tails
 |