「Ansi Common Lisp」5章練習問題 - Haskell版
3. 引数の平方を返す関数を定義せよ。ただし、引数が5以下の正の整数である場合は平方の計算を行わないものとする。
mySquare :: Int -> Int mySquare x | (x >= 0 && x <= 5) = x | otherwise = x * x main = do print $ mySquare 0 print $ mySquare 5 print $ mySquare (-5) print $ mySquare 6
結果はこう。
0 5 25 36
-5はカッコをつけないと、
print $ (mySquare - 5)
と扱われてしまうので注意らしいです。
No instance for (Num (Integer -> Integer)) arising from use of `-' at ex5-3.hs:9:18-28 Possible fix: add an instance declaration for (Num (Integer -> Integer)) In the second argument of `($)', namely `mySquare - 5' In the expression: print $ (mySquare - 5) In a 'do' expression: print $ (mySquare - 5)
5. オブジェクトxとベクタvを引数として、vの中でxの直前にくる全オブジェクトを返すような関数を定義せよ。
precedes :: (Eq a) => a -> [a] -> [a] precedes x [] = [] precedes x (v:[]) = [] precedes x (v:vs) = let result = precedes x vs in if (head vs) == x then if elem v result then result else v : result else result main = print $ precedes 'a' "abracadabra"
precedes x (v:[]) = []
みたいな書き方できるんですね。ちょっとした発見でした。
結果はこう。
"cdr"
6. 1つのオブジェクトと1つのリストを引数として、このリストの要素間にオブジェクトを挿入した新しいリストを返す関数を、反復と再帰の両方の方法で定義せよ。
intersperse :: String -> String intersperse x = cdr $ concatMap (\n -> "-" ++ [n]) x cdr :: [a] -> [a] cdr [] = [] cdr (x:xs) = xs main = print $ intersperse "abcd"
結果はこう。
"a-b-c-d"
7. 数のリストを引数として、連続するペアの差が1となる場合に真を返す関数を以下の3つの方法で定義せよ。
testListDiffIs1 :: [Int] -> Bool testListDiffIs1 [] = False testListDiffIs1 (x:[]) = True testListDiffIs1 (x:xs) = (abs(x - (head xs)) == 1) && (testListDiffIs1 xs) main = do print $ testListDiffIs1 [1,2,3] print $ testListDiffIs1 [3,2,1] print $ testListDiffIs1 [3,1,2] print $ testListDiffIs1 [3,2,3] print $ testListDiffIs1 [3,3,2]
結果はこう。
True True False True False
8. ベクタの要素の最大・最小の2値を返す(二重でない)再帰関数を定義せよ。
vectorMaxMin :: [Int] -> (Int,Int) vectorMaxMin [] = (0,0) vectorMaxMin (x:[]) = (x,x) vectorMaxMin (x:xs) = let result = vectorMaxMin xs in case x of x | x > (fst result) -> (x, (snd result)) | x < (snd result) -> ((fst result), x) | otherwise -> result main = print $ vectorMaxMin [3,1,2,5,4]
Haskellにはelseifがない(?)上に、
if 〜 then 〜 else (if 〜 then 〜 else 〜)みたいに
ネストしたif文を書けないらしい。ほんとかなあ。。
とりあえずcase式を使うことでなんとか出来ましたが、
こっちの方が見やすいですね。
結果はこう。
(5,1)