{-# LANGUAGE ScopedTypeVariables #-} -- | -- = 第2章 練習問題 E -- module TFwH.Chap02.ExE where import Control.Exception import Data.List -- $setup -- | -- -- @ -- first :: (a -> Bool) -> [a] -> a -- first p = head . filter p -- @ -- -- @ -- first :: (a -> Bool) -> [a] -> a -- first p xs | null xs = error "Empty list" -- | p x = x -- | otherwise = firstB p (tail xs) -- where -- x = head xs -- @ -- -- >>> let firstS p = head . filter p -- Susan版 -- >>> first isSquare nums == firstS isSquare nums -- True first :: (a -> Bool) -> [a] -> a first p xs | null xs = error "Empty list" | p x = x | otherwise = first p (tail xs) where x = head xs -- | -- Susan の first' :: (b -> Bool) -> (a -> b) -> [a] -> b -- -- @ -- first' :: (b -> Bool) -> (a -> b) -> [a] -> b -- first' p f = head . filter p . map f -- @ -- -- Beaver の first' -- -- @ -- first' :: (b -> Bool) -> (a -> b) -> [a] -> b -- first' p f xs | null xs = error "Empty list" -- | p x = x -- | otherwise = first' p f (tail xs) -- where -- x = f (head xs) -- @ -- -- >>> let first'S p f = head . filter p . map f -- >>> first' isSquare (subtract 1 . (2*)) nums == first'S isSquare (subtract 1 . (2*)) nums -- True first' :: (b -> Bool) -> (a -> b) -> [a] -> b first' p f xs | null xs = error "Empty list" | p x = x | otherwise = first' p f (tail xs) where x = f (head xs) -- | -- より好ましい betterFistB (Beaver 版) -- -- @ -- betterFirstB :: (a -> Bool) -> [a] -> Maybe a -- betterFirstB p xs -- | null xs = Nothing -- | p x = Just x -- | otherwise = betterFirstBeaver p (tail xs) -- where -- x = head xs -- @ -- betterFirstB :: (a -> Bool) -> [a] -> Maybe a betterFirstB p xs = case uncons xs of Nothing -> Nothing Just (y,ys) -> if p y then Just y else betterFirstB p ys -- | -- より好ましい betterFistS (Susan 版) -- -- @ -- betterFirstS :: (a -> Bool) -> [a] -> Maybe a -- betterFirstS p = maybe Nothing (Just . fst) . uncons . filter p -- @ -- -- >>> sum nums' -- 499999500000 -- >>> betterFirstB isSquare nums' == betterFirstS isSquare nums -- True betterFirstS :: (a -> Bool) -> [a] -> Maybe a betterFirstS p = maybe Nothing (Just . fst) . uncons . filter p -- | -- テスト用データ 1 -- -- @ -- nums :: [Int] -- nums = [999999, 999998 .. 0] -- @ nums :: [Int] nums = [999999, 999998 .. 0] -- | -- テスト用データ 2 -- nums と同値ですが,先頭の要素を取り出した時点で長さ1000000のリストができています. -- nums' :: [Int] nums' = let nums = [999999, 999998 .. 0] in if nums == reverse (reverse nums) then nums else nums -- | -- お試し用述語 -- -- @ -- isSquare :: Int -> Bool -- isSquare = (==) <*> (^2) . round . sqrt . fromIntegral -- @ -- isSquare :: Int -> Bool isSquare = (==) <*> (^2) . round . sqrt . fromIntegral -- | -- 多相関数 polyN :: Maybe a -> Maybe a を生成する関数 -- poly :: Int -> (Maybe a -> Maybe a) poly 0 x = case x of Nothing -> Nothing Just y -> Nothing poly 1 x = case x of Nothing -> Nothing Just y -> Just y poly 2 x = case x of Nothing -> Nothing Just y -> Just undefined poly 3 x = case x of Nothing -> Nothing Just y -> undefined poly 4 x = case x of Nothing -> Just undefined Just y -> Nothing poly 5 x = case x of Nothing -> Just undefined Just y -> Just y poly 6 x = case x of Nothing -> Just undefined Just y -> Just undefined poly 7 x = case x of Nothing -> Just undefined Just y -> undefined poly 8 x = case x of Nothing -> undefined Just y -> Nothing poly 9 x = case x of Nothing -> undefined Just y -> Just y poly 10 x = case x of Nothing -> undefined Just y -> Just undefined poly 11 x = case x of Nothing -> undefined Just y -> undefined poly 12 x = Nothing poly 13 x = Just undefined poly 14 x = Just (case x of Nothing -> undefined Just y -> y ) -- | -- 型クラスShowのインスタンスである型の値を表示 IO () -- prna :: Show a => a -> IO String prna a = catch (return $ show a) (\ (e :: SomeException) -> return "⊥") -- | -- Maybe a の値を表示 IO () -- prn :: Show a => Maybe a -> IO () prn m = catch (case m of Nothing -> putStrLn "Nothing" Just x -> putStrLn . ("Just "++) =<< prna x ) (\ (e :: SomeException) -> putStrLn "⊥") -- | -- テスト用引数 -- samples = [Nothing, Just (), Just undefined, undefined] :: [Maybe ()] -- | -- 表示テスト -- -- >>> test -- Nothing -- Nothing -- Nothing -- ⊥ -- ----- -- Nothing -- Just () -- Just ⊥ -- ⊥ -- ----- -- Nothing -- Just ⊥ -- Just ⊥ -- ⊥ -- ----- -- Nothing -- ⊥ -- ⊥ -- ⊥ -- ----- -- Just ⊥ -- Nothing -- Nothing -- ⊥ -- ----- -- Just ⊥ -- Just () -- Just ⊥ -- ⊥ -- ----- -- Just ⊥ -- Just ⊥ -- Just ⊥ -- ⊥ -- ----- -- Just ⊥ -- ⊥ -- ⊥ -- ⊥ -- ----- -- ⊥ -- Nothing -- Nothing -- ⊥ -- ----- -- ⊥ -- Just () -- Just ⊥ -- ⊥ -- ----- -- ⊥ -- Just ⊥ -- Just ⊥ -- ⊥ -- ----- -- ⊥ -- ⊥ -- ⊥ -- ⊥ -- ----- -- Nothing -- Nothing -- Nothing -- Nothing -- ----- -- Just ⊥ -- Just ⊥ -- Just ⊥ -- Just ⊥ -- ----- -- Just ⊥ -- Just () -- Just ⊥ -- Just ⊥ -- test :: IO () test = mapM_ sequence_ $ intersperse [putStrLn "-----"] $ map (flip map samples) ps where ps = map ((prn .) . poly) [0..14]