Created
July 22, 2012 17:58
-
-
Save shtaag/3160513 to your computer and use it in GitHub Desktop.
Start_Haskell_2 exercise in chap.5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
問題13 | |
リストのリストを取って、要素のリストを連結する関数concat :: [[a]] -> [a]は 第6章の演習問題で定義した。これをfoldrを使って実装した関数concatRを 定義せよ。さらに、foldlを使って実装した関数concatLを定義せよ。 | |
以下の実行例で自分の定義が正しいことを確認せよ。 | |
> concatR [[1,2],[3],[],[4,5]] | |
[1,2,3,4,5] | |
> concatL [[1,2],[3],[],[4,5]] | |
[1,2,3,4,5] | |
> concatR [] | |
[] | |
> concatL [] | |
[] | |
注)実行には以下のモジュールをcabal installする必要があるかも | |
cabal install test-framework | |
cabal install test-framework-quickcheck | |
cabal install test-framework-quickcheck2 | |
cabal install test-framework-hunit | |
cabal install test-framework-th | |
cabal install criterion | |
\begin{code} | |
{-# LANGUAGE TemplateHaskell #-} | |
import Data.List | |
import Test.QuickCheck | |
import Test.HUnit | |
import Test.Framework.TH | |
import Test.Framework.Providers.HUnit | |
import Test.Framework.Providers.QuickCheck2 | |
import Criterion.Main | |
-- 俺なりの実装 | |
concatR :: [[a]] -> [a] | |
concatR = foldr (\x acc -> x ++ acc) [] | |
concatL :: [[a]] -> [a] | |
concatL = foldl (++) [] | |
concatL' :: [[a]] -> [a] | |
concatL' = foldl' (++) [] | |
-- test-framework実行のためのmain | |
main :: IO () | |
main = $(defaultMainGenerator) | |
-- main = runTests concatTests (TemplateHaskellを使わない場合) | |
-- criterion実行のためのmain | |
mainBench = do | |
let input = [[1..100000],[1..100000],[1..100000]] | |
defaultMain | |
[bench "concatR" $ nf concatR (input :: [[Int]]) | |
, bench "concatL" $ nf concatL (input :: [[Int]]) | |
, bench "concatL'" $ nf concatL' (input :: [[Int]]) | |
] | |
-- prop_で、関数が満たして欲しい性質を書く。TemplateHaskellがquickCheckに渡してくれる。 | |
prop_concatR :: [Int] -> [Int] -> [Int] -> Bool | |
prop_concatR xs ys zs = xs ++ ys ++ zs == concatR [xs, ys, zs] | |
prop_concatL :: [Int] -> [Int] -> [Int] -> Bool | |
prop_concatL xs ys zs = xs ++ ys ++ zs == concatL [xs, ys, zs] | |
prop_concatL' :: [Int] -> [Int] -> [Int] -> Bool | |
prop_concatL' xs ys zs = xs ++ ys ++ zs == concatL' [xs, ys, zs] | |
-- case_でHUnitテストケースを書く。TemplateHaskellがHUnitに渡してくれる。 | |
case_cocatR_n :: Assertion | |
case_cocatR_n = (concatR [[1,2],[3],[],[4,5]]) @?= [1,2,3,4,5] | |
case_cocatR_emp :: Assertion | |
case_cocatR_emp = (concatR []) @?= ([] :: [Int]) | |
case_cocatL_n :: Assertion | |
case_cocatL_n = (concatL [[1,2],[3],[],[4,5]]) @?= [1,2,3,4,5] | |
case_cocatL_emp :: Assertion | |
case_cocatL_emp = (concatL []) @?= ([] :: [Int]) | |
case_cocatL'_n :: Assertion | |
case_cocatL'_n = (concatL' [[1,2],[3],[],[4,5]]) @?= [1,2,3,4,5] | |
case_cocatL'_emp :: Assertion | |
case_cocatL'_emp = (concatL' []) @?= ([] :: [Int]) | |
-- 以下はtest-frameworkを使う前に書いたもの。メモのため残しておく。 | |
-- HUnitで複数のTestを実行する関数を定義 | |
runTests :: [Test] -> IO Counts | |
runTests ts = runTestTT $ TestList ts | |
-- Test.Frameworkを使わないときはこれらテストケースをmainからrunTests concatTestsを実行 | |
concatTests :: [Test] | |
concatTests = map TestCase | |
[ assertEqual "concatR [[1,2],[3],[],[4,5]] " [1,2,3,4,5] (concatR [[1,2],[3],[],[4,5]]) | |
,assertEqual "concatL [[1,2],[3],[],[4,5]] " [1,2,3,4,5] (concatL [[1,2],[3],[],[4,5]]) | |
,assertEqual "concatL' [[1,2],[3],[],[4,5]] " [1,2,3,4,5] (concatL' [[1,2],[3],[],[4,5]]) | |
,assertEqual "concatR [] " ([] :: [Int]) (concatR []) | |
,assertEqual "concatL [] " ([] :: [Int]) (concatL []) | |
,assertEqual "concatL' [] " ([] :: [Int]) (concatL' []) | |
] | |
\end{code} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment