Haskell H99 Question 11
http://www.haskell.org/haskellwiki/99_questions/11_to_20
import Data.List data ListItem a = Single a | Multiple Int a deriving (Show) --自分で作った解答 encodeModified :: Eq a => [a] -> [ListItem a] encodeModified xs = map (listToAmount) (group xs) where listToAmount :: Eq a => [a] -> (ListItem a) listToAmount (x:xs) | length (x:xs) > 1 = Multiple (length (x:xs)) x | otherwise = Single x --模範解答 --Question 9 からの引用 encode xs = map (\x -> (length x,head x)) (group xs) encodeModified' :: Eq a => [a] -> [ListItem a] encodeModified' = map encodeHelper . encode where encodeHelper (1,x) = Single x encodeHelper (n,x) = Multiple n x
頑張ってみたのですが、どうしてもdata型を作ることができなかったので答え見ました。。
データ型とか、インスタンスとか型クラスとか、あんまり理解できていないようなので、どこかで勉強しないと。
データ型の宣言
data ListItem a = Single a | Multiple Int a deriving (Show)
ListItemの宣言です。見たらこういうもんかと思いますが、こういう形に自分で作ることはできませんでした。
ListItem aはSingle aかMultiple Int aという形をとるという単純なものですが、型変数に任意の型クラスを適用とすると構文エラーになってしまって断念。
そういうことはできないのかしら。。
derivingとは派生などという意味らしいです。構文については、そのうちしっかり勉強して書きます。
自分で作った解答
encodeModified :: Eq a => [a] -> [ListItem a] encodeModified xs = map (listToAmount) (group xs) where listToAmount :: Eq a => [a] -> (ListItem a) listToAmount (x:xs) | length (x:xs) > 1 = Multiple (length (x:xs)) x | otherwise = Single x
第9問のやり方を参考にして、mapとgroupを使いました。
map用にリストを引数にListItemを返す関数を作り、その中で条件によってSingleかMultipleを返すようにしました。
まあまあいいじゃんと思いましたが、模範解答では関数合成を使用していました。そっちのほうがエレガントに見えますね。
模範解答
--Question 9 からの引用 encode xs = map (\x -> (length x,head x)) (group xs) encodeModified' :: Eq a => [a] -> [ListItem a] encodeModified' = map encodeHelper . encode where encodeHelper (1,x) = Single x encodeHelper (n,x) = Multiple n x
以下のように関数が定義されています。
encode :: Eq t => [t] -> [(Int, t)] map encodeHelper :: [(Int, a)] -> [ListItem a] (ちなみに、encodeHelper :: (Int, a) -> ListItem a)
これにより、encode の戻り値をそのままmap encodeHelperにつなげることができますね。