2014/07/22 Haskellその3 練習問題を解く2

StartHaskell2 wikiの問題を解いてみる

問1:偶数と奇数を分ける。

				
oddEven :: [Int] -> ([Int],[Int])
oddEven [] = ([],[])
oddEven (x:xs) 
  | odd x  ==True = tupleC ([x],[]) $ oddEven xs
  | otherwise = tupleC ([],[x]) $ oddEven xs
    where
      tupleC :: ([a],[b]) -> ([a],[b]) -> ([a],[b])
      tupleC (x1,y1) (x2,y2) = (x1 ++ x2 ,y1 ++ y2)
			    
			

問2:等比数列

				
gp :: (Num a) => a -> a -> [a]
gp n r = n : map (*r) (gp n r)
			    
			

問3:フィボナッチ数列のn番目を返す関数を作ろう

				
fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib(n-1) + fib (n-2)
			    
			

高階関数

問4:部分適用された関数の型

				
※Ans : (答え)

Q1: max 5

max の定義は 
max :: (Ord a) => a -> a -> a
max 5は (Ord a) => a -> aとなる。
そして、5はNum型のインスタンスとなるので、
型クラス制約にNumがつく。
つまり、
Ans1 : (Num a,Ord a) => a -> a
である。

Q2:takeWhile (<100)
takeWhileの定義は
takeWhile :: (a -> Bool) -> [a] -> [a]
述語を受け取り、Falseになるまでのリストを返す。
例: takeWhile(<100) [99,100,101,99]
結果: [99]

takeWhile (<100) は
(Num a) => [a] -> [a] となる。
(<100)でNum型のインスタンスと決定しているからである。
さらに、順序も比較できなければいけないのでOrd型のインスタンスでもある。
つまり
Ans2 : (Num a,Ord a) => [a] -> [a]
である。

TIPS:似ている関数にfilterがあるが、filterはTrueであるものを全て返す関数である。
     上の例のtakeWhileをfilterにすると、
結果: [99,99] となる。

Q3 : zipWith (+)
zipWithの定義は
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWithは(a -> b -> c)の関数を受け取り、それを[a] と [b]に適用するものである。
例  : zipWith (+) [1,2,3] [1,2,3]
結果: [2,4,6]

zipWith (+) は
(+)の関数が Num a という型クラス制約を持っているので
zipWith の a と b は Num型のインスタンスとなる。
つまり、
zipWith :: (Num a) => (a -> a -> a) -> [a] -> [a] -> [a]
となる。
これを部分適用するので、zipWith (+) は 
Ans 3: (Num a) => [a] -> [a] -> [a]
となる。			    
			

問5:コラッツ数列

				
collatz :: Int -> [Int]
collatz 0 = error "Not a Natural Number"
collatz 1 = 1 : []
collatz n 
  | even n = n : collatz(n `div` 2)
  | otherwise = n : collatz(n * 3 + 1)
			    
			

問6:関数適用、関数合成

				
以下の関数の括弧を、関数適用($)で書き換えてみよう。
g :: [a] -> [a]
g xs = tail (tail (tail (tail xs)))

f :: [Int] -> [Int]
f xs = take 10 (map (*3) (filter even xs))
			    
			
				
g' :: [a] -> [a]
g' xs = tail $ tail $ tail $ tail xs

f' :: [Int] -> [Int]
f' xs = take 10 $ map (*3) $ filter even xs