練習問題

入門Haskell―はじめて学ぶ関数型言語」 p.101 より。

ところで,あるリストに複数の型を含めたい場合にはどうしたらいいか,という話ですが,そういう場合にも data は便利です。たとえば次のように
data MyType = I Int | F Float | C Char
ここでたとえば [I 10, F 10, C 'a'] のようなリストがあるとします。

(1)[MyType] から C 要素だけ取り出す関数 filterC を書きなさい。

これは C 要素であるか否かを判定する関数を作って filter すればいいんだろう。判定には case を使って場合分けすればいい。

 filterC :: [MyType] -> [MyType]
 filterC = filter isC
   where isC x = case x of
                   I a -> False
                   F a -> False
                   C a -> True

結果。

 *Main> filterC [I 10, F 10, C 'a']
 [C 'a']

OK。

(2) [MyType] から I 要素だけを取り出してその合計を計算する sumI を書きなさい。

 sumI :: [MyType] -> Int
 sumI = sum . map pickI
   where pickI x = case x of
                     I a       -> a
                     otherwise -> 0
 *Main> sumI [I 10, F 10, C 'a']
 10

なるほど,otherwise も使えるんだな。

(3) [MyType] から,I 要素はそのまま,F 要素は整数にし(truncate 関数が使えます),C 要素はその文字の文字コードを計算し( Data.Char をインポートすれば ord 関数が計算してくれます),その合計を計算する mySum 関数を書きなさい。

 import Data.Char
 
 mySum :: [MyType] -> Int
 mySum = sum . map toInt
   where toInt x = case x of
                     I a -> a
                     F a -> truncate a
                     C a -> ord a
 *Main> mySum [I 10, F 10, C 'a']
 117

'a' のコードは 97 だから全部足すと 117。OK。


ところで,GHCi で表示できるように,MyType の宣言は次のようにしている。

 data MyType = I Int | F Float | C Char deriving (Show)