ふつける:5,6章読んだ

ふつける6章まで読了.5章の,遅延評価の考え方は凄い.関数型言語ならではだなぁと思った(そうでもない?).中でも,最外簡約,グラフ簡約が.こいつぁすげぇや.


6章では色んな型ってのを(今更ながら)学んだのだけども,その途中,ふとzipWithをmapとzipを使って書けるかしらと思ったので,ちょっとやってみました.

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f x y = map (fs f) $ zip x y
                        where fs f x = f (fst x) (snd x)


fsは結局,置き換えようと思えば

k x = f (g x) (h x)

なんで,なんとか関数結合を使って表せないかなと考えたものの,なんだか訳が分かんなくなったのでやめました.
Preludeの定義を見てみると,

zip = zipWith (,)

なんですね.しかも結局zipWithは再帰定義だし.んじゃzipWithをzipを使って書く,ってすごく効率が悪いんだな.

タプル

タプルを作る時,

(,) a b

と出来るという事を知ったのですが,これもちゃんと型を見てみると

Main> :t (,)
(,) :: a -> b -> (a,b)
Main> :t (,,)
(,,) :: a -> b -> c -> (a,b,c)

と.それじゃこれはどうなる.

Main> :t (,,,,,,,,,,,,,,,,)
(,,,,,,,,,,,,,,,,) :: a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k
 -> l -> m -> n -> o -> p -> q -> (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q)

ふおぉ,根性だな.関数定義というより言語仕様って感じだなぁ.

遅延評価

これを考えてる途中,

f = (*)
g = (fst)
h = (snd)

k = (.(.f)) (.g) (.h)

と言うのを書いてたんですが,型を見てみると

Main> :t k
k :: (Integer,a) -> (b,Integer) -> Integer

と.
型推論!最外簡約!

追記

b2oxさんの助言により,zipWithがスッキリしました.

zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f x y = map (uncurry f) $ zip x y

Hoogλe,大切にしないと.