real world haskell(1)[Exercise3]
real world haskellを買ったので読んでいる。exercise3をやってみた。grahum-scanはもう少しきれいに書けそうな気がする。
import Data.List -- http://book.realworldhaskell.org/read/defining-types-streamlining-functions.html ---Exercise 3.1 length1 [] = 0 length1 (_:xs) = 1 + (length1 xs) --tail recursion(末尾再帰を最適化しないっけ?) length2 xs = length' xs 0 where length' [] n = n length' (_:xs) n = length' xs (n + 1) --foldl length3 = foldl (\ n _ -> n + 1) 0 ---Exercise 3.2 type Weight = Double type Height = Double type Name = String data Info = Human Name Height Weight deriving (Show) -- :type Human -- => Human :: Name -> Height -> Weight -> Info bmi :: Info -> (String, Double) bmi (Human name h w) = (name, w / (h * h) ) -- bmi (Human "foo" 1.6 50.0) -- => ("foo",19.531249999999996) ---Exercise 3.3 mean xs = fromIntegral (sum xs) / fromIntegral (length xs) ---Exercise 3.4 parindrome xs = xs ++ (reverse xs) ---Exercise 3.5 is_parindrome xs = left == reverse right where len = length xs hulf = len `div` 2 (left,right) = if odd len then let (l,r) = splitAt hulf xs in (l ,tail r) else splitAt hulf xs ---Exercise 3.6 sortByLength = sortBy (\x y -> compare (length x) (length y)) ---Exercise 3.7 intersperse1 delim [xs] = [xs] intersperse1 delim (x:xr) = x : delim : (intersperse1 delim xr) intersperse2 = Data.List.intersperse ---Exercise 3.8 data Tree a = Node a (Tree a) (Tree a) | Empty deriving (Show) ---Exercise 3.9 treeHeight Empty = 0 treeHeight (Node _ l r) = 1 + max (treeHeight l) (treeHeight r) ---Exercise 3.10 data Direction = LeftTurn | Straight | RightTurn deriving (Show) ---Exercise 3.11 calcAngle a b c = (abx * acy) - (aby * acx) where size (x0,y0) (x1,y1) = (x1-x0, y1-y0) ((abx,aby), (acx,acy)) = (size a b , size a c) calcDirection a b c = direction $ calcAngle a b c where direction 0 = Straight direction x | x > 0 = LeftTurn | otherwise = RightTurn ---Exercise 3.12 mapTriple fn [a,b,c] = [fn a b c] mapTriple fn (a:rest@(b:c:_)) = (fn a b c) : mapTriple fn rest calcDirections = mapTriple calcDirection ---Exercise 3.13 findSmallest ps = minimumBy compare' ps where compare' (ax,ay) (bx,by) = case (compare ay by) of EQ -> compare ax bx ord -> ord grahumScan ps@(_:_:_:_) = collect [a,smallest] ps' where smallest = findSmallest ps (a:ps') = sortBy (compare' calcAngle') ps where smallest2 = let(x,y) = smallest in (x+1,y) compare' fn x y = compare (fn x) (fn y) calcAngle' = calcAngle smallest smallest2 collect acc [] = reverse acc collect acc@[b,a] ps@(c:pr) = case (calcDirection a b c) of LeftTurn -> collect (c : acc) pr _ -> collect [b,a] pr collect acc@(b:rest@(a:_)) ps@(c:pr) = case (calcDirection a b c) of LeftTurn -> collect (c : acc) pr _ -> collect rest ps grahumScan ps = ps