RWH 3章章末

-- 3
avg :: (Fractional a) => [a] -> a
avg [] = 0
avg xs = sum xs / fromIntegral (length xs)

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

-- 5
isPalindrome :: (Eq a) => [a] -> Bool
isPalindrome xs = xs == (reverse xs)

-- 6
sortByLength :: (Ord a) => [[a]] -> [[a]]
sortByLength xs = sortBy compare xs

-- 7
intersperse :: a -> [[a]] -> [a]
intersperse _ [] = []
intersperse _ (x:[]) = x
intersperse s (x:xs) = x ++ [s] ++ intersperse s xs

-- 8
data Tree a = Node a (Tree a) (Tree a)
            | Empty
              deriving (Show)

height :: Tree a -> Int
height Empty = 0
height (Node _ l r) = 1 + max (height l) (height r)

-- 9
-- ClockWise, CounterClockWise, STraight
data Direction = CW | CCW | ST
                 deriving (Show)

-- 10
data Cartesian2D = Cartesian2D {
    xCoord :: Double,
    yCoord :: Double
    } deriving (Eq, Show)

-- cf. http://www5d.biglobe.ne.jp/~noocyte/Programming/Geometry/RotationDirection.html
direction :: Cartesian2D -> Cartesian2D -> Cartesian2D -> Direction
direction a b c
    | cp == 0   = ST
    | cp >  0   = CCW
    | otherwise = CW
    where cp = (xCoord a - xCoord b) * (yCoord b - yCoord c) - (yCoord a - yCoord b) * (xCoord b - xCoord c)

-- 11
directionList :: [Cartesian2D] -> [Direction]
directionList (p1:ps@(p2:p3:_)) = (direction p1 p2 p3):directionList ps
directionList _ = []

3は空リストに対して0を返す定義も書いてみたけど、いらないかも。その場合は0除算になってNaN。
5は型シグネチャが最初書けなかったので、シグネチャなしで定義だけ書いてHaskell型推論してもらった。[a] -> Boolだけだと[a]が同値比較できると限らないのでEq aが必要なのね。
7。振る舞いを満たすように順に定義してるだけ。空リストなら空リスト。サブリストが1個だけならそのまま。2個以上あれば1個目に区切り子を繋いで残りを再帰
8。Emptyの高さは0。Nodeならそのノード自身の高さ1と、左右の子で高さを比べて高いほうの和。
9。時計回り、反時計回り、直線。
10。座標は3.3.1で出てきたCartesian2D型を3.5のレコード構文で。式は外積使う方法があったよねーとだけ覚えていたのを検索した。
11。パターンマッチがキモい。3個以上の要素をもっているリストなら頭3個でDirectionを計算して先頭の1個を除いたリストを再帰。あとはマッチしなくて2個以下なので空リスト。