学習したこと
Haskellで、いくつか学習したことをまとめます。
モジュールに定義された関数は次のようにして確認することができます。
bash-3.2$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :browse Data.List
もし、使えるパッケージを確認したいならば、次のようにして確認することができます。
bash-3.2$ ghc-pkg list
この辺で、Google検索しようとするはずですが、それでもまだターミナルで、興味のあるパッケージのexposed-modulesを確認したいならば、次のようにして確認することができます。
bash-3.2$ ghc-pkg describe QuickCheck | more
そうして、そのモジュールに定義された関数を確認したいなら、冒頭の手続きを行います。。
けど、特に問題がなければ、Hoogleで検索しましょう。
あとがき
なぜ、今更、Haskellか?それは関数プログラミングの楽しみを読んでみたかったからです。
「関数プログラミングの楽しみ」を読み始めたときは基礎的な知識がない状態でしたので、Haskell98のチュートリアルをすこし読みました。まずつまづいたことはType constructorとData constructorです。
ふつうのHaskellプログラミングを読むことで、Type constructorとData constructorについて理解を深めることができました。要点は、「型を書けるところにType constructorが使えて、値を書けるところにData constructorが使える」です。
「ふつうのHaskellプログラミング」ではパターンマッチをいくつかに分類していて、データコンストラクタパターンと呼ばれるパターンマッチがあります。これが使えるようになると、「関数プログラミングの楽しみ」の第1章の二分ヒープ木を処理する関数も使えるようになりました。
data (Ord a) => Tree a = Null | Fork a (Tree a) (Tree a)
isEmpty :: (Ord a) => Tree a -> Bool
isEmpty Null = True
isEmpty (Fork x a b) = False
minElem :: (Ord a) => Tree a -> a
minElem (Fork x a b) = x
deleteMin :: (Ord a) => Tree a -> Tree a
deleteMin (Fork x a b) = merge a b
insert :: (Ord a) => a -> Tree a -> Tree a
insert x a = merge (Fork x Null Null) a
merge :: (Ord a) => Tree a -> Tree a -> Tree a
merge a Null = a
merge Null b = b
merge a b
| minElem a <= minElem b = join a b
| otherwise = join b a
join (Fork a' x y) b = Fork a' x (merge y b)
main = do
if isEmpty (Fork 1 (Fork 3 Null Null) (Fork 4 Null Null))
then putStrLn "empty"
else putStrLn $ show $ minElem $
merge (Fork 7 Null Null) $
merge (Fork 8 Null Null) (Fork 5 Null Null)
次につまづいたことはQuickCheckモジュールの使い方です。これはReal World Haskellの第11章をすこし読んで使い方を確認しました。QuickCheckモジュールが使えるようになると、「関数プログラミングの楽しみ」の第2章が読めるようになり始めました。これは始まったばかりです。。。
import Test.QuickCheck
import Data.List
qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort (x:xs) = qsort lhs ++ [x] ++ qsort rhs where
lhs = filter (< x) xs
rhs = filter (>= x) xs
prop_idempotent :: [Integer] -> Bool
prop_idempotent xs = qsort (qsort xs) == qsort xs
prop_minimum :: [Integer] -> Bool
prop_minimum xs = head (qsort xs) == minimum xs
prop_minimum' :: [Integer] -> Property
prop_minimum' xs = not (null xs) ==> head (qsort xs) == minimum xs
main = do
quickCheck (prop_idempotent)
quickCheck (prop_minimum)
quickCheck (prop_minimum')
「関数プログラミングの楽しみ」は私にとって少し手に余る内容ですが、内容が充実しているので、時間を掛ければ楽しめると思います!