第三章

このブログは移転しました
3秒後にリダイレクトされますblog.ltakeshi.info

3.3代数データ型

うまく使えばバグを生みにくくすることが出来て良さそう。

-- x,yの座標
data Cartesian2D = Cartesian2D Double Double
                   deriving (Eq, Show)
-- 偏角と長さ
data Polar2D = Polar2D Double Double
               deriving (Eq, Show)

という同じ型の二つの要素を持つデータ型を用意してみる。ghciで走らせて遊んでみると、

Main> Cartesian2D (pi / 4) 2
Cartesian2D 0.7853981633974483 2.0
Main> Polar2D (pi / 4) 2
Polar2D 0.7853981633974483 2.0

と同じ値を示すが、比較してみると

Main> Cartesian2D (pi / 4) 2 == Polar2D (pi / 4) 2

<interactive>:1:26:


    Couldn't match expected type `Cartesian2D'
           against inferred type `Polar2D'
    In the second argument of `(==)', namely `Polar2D (pi / 4) 2'
    In the expression: Cartesian2D (pi / 4) 2 == Polar2D (pi / 4) 2
    In the definition of `it':
        it = Cartesian2D (pi / 4) 2 == Polar2D (pi / 4) 2

怒られてしまう。ただ、同じ事をタプルで表現すると

Main> ((pi / 4), 2) == ((pi / 4), 2)
True

となる。ということでうまく使いましょうってことで。
RWHの中ではコードの中で広く使う場合はdata宣言を使って、局所的なものはタプルで良いのじゃないでしょうかって感じで書いてある。

3.5レコード構文

要は以下の定義はいちいち面倒くさいので

data Customer' = Customer' Int String [String]
                 deriving (Show)
customerID' (Customer' id _ _) = id
customerName' (Customer' _ name _) = name
customerAddress' (Customer' _ _ address) = address

こんな感じにしてしまいましょうということ。

data Customer = Customer {
      customerID      :: CustomerID
    , customerName    :: String
    , customerAddress :: Address
    } deriving (Show)

基本的には同じものを表しているので、

Main> customerID' (Customer' 123 "aaa" ["hoge","fuga"]) == customerID (Customer 123 "aaa" ["hoge","fuga"])
True

となる。

3.7再帰

練習問題1

toList :: List a -> [a]
toList (Cons x xs) = x:toList xs
toList Nil = []

練習問題2
散々考えたけどよく分からん。とりあえず持ち越し。

3.13ガード条件節の評価

練習問題1,2(同時に済ませた。)

mylength :: [a] -> Int
mylength (x:xs) = 1 + mylength xs
mylength [] = 0

練習問題3
とりあえず見たまんま。fromIntegralを使わないとエラーが出る。

average xs = fromIntegral(sum xs) / fromIntegral(length xs)

練習問題4
引数で与えられたリストとそのリストをreverseしたものを連結させる。

palindrome :: [a] -> [a]
palindrome xs = xs ++ reverse xs

練習問題5
かなりいい加減。こんなんで良いのだろうか?
やってることは引数のリストを半分にして前半の部分と後半の部分をreverseしたものが同一なら
回文と判定。

check_palindrome :: (Eq a) => [a] -> Bool
check_palindrome xs = if fst x == (reverse $ snd x)
                      then True
                      else False
    where x = splitAt (length xs `div` 2) xs

とりあえず、今日はここまで。続きは後日。