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個以下なので空リスト。