コンテキストでの型の操作 Applicative型クラス:関数をコンテキスト内で使用する ユーザー入力、Maybe型、<$>演算子(Functor)と<*>演算子
入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)のUNIT5(コンテキストでの型の操作)、LESSON 28(Applicative型クラス:関数をコンテキスト内で使用する)、28.5(練習問題)Q28-3の解答を求めてみる。
コード
import qualified Data.Map as Map
data RobotPart = RobotPart { name :: String
, cost :: Double} deriving Show
leftArm :: RobotPart
leftArm = RobotPart { name = "左腕", cost = 1000}
rightArm :: RobotPart
rightArm = RobotPart { name = "右腕", cost = 1025}
robotHead :: RobotPart
robotHead = RobotPart { name = "頭", cost = 5092.25}
leftLeg :: RobotPart
leftLeg = RobotPart { name = "左足", cost = 975}
rightLeg :: RobotPart
rightLeg = RobotPart { name = "右足", cost = 1000}
partsDB :: Map.Map Int RobotPart
partsDB = let keys = [1..5]
vals = [leftArm,
rightArm,
robotHead,
leftLeg,
rightLeg]
keyVals = zip keys vals
in Map.fromList keyVals
getID :: IO Int
getID = do read <$> getLine
getCost :: Maybe RobotPart -> Maybe Double
getCost part = cost <$> part
minPart :: Maybe RobotPart -> Maybe RobotPart -> Maybe RobotPart
minPart part1 part2 = let cost1 = getCost part1
cost2 = getCost part2
minCost = min <$> cost1 <*> cost2
in if minCost == cost1
then part1
else part2
printPart :: Maybe RobotPart -> IO ()
printPart Nothing = print "Invalid id"
printPart (Just part) = putStrLn (mconcat ["安いのは", name part, "で", show (cost part)])
main :: IO ()
main = do
putStrLn "2つのIDを入力"
id1 <- getID
id2 <- getID
let part1 = Map.lookup id1 partsDB
let part2 = Map.lookup id2 partsDB
let part = minPart part1 part2
printPart part
入出力結果(Terminal, Zsh)
% ghc sample3.hs
Loaded package environment from /Users/…/.ghc/x86_64-darwin-8.10.5/environments/default
[1 of 1] Compiling Main ( sample3.hs, sample3.o )
Linking sample3 ...
% ./sample3
2つのIDを入力
1
2
安いのは左腕で1000.0
% ./sample3
2つのIDを入力
1
3
安いのは左腕で1000.0
% ./sample3
2つのIDを入力
1
4
安いのは左足で975.0
% ./sample3
2つのIDを入力
4
5
安いのは左足で975.0
% ./sample3
2つのIDを入力
4
6
"Invalid id"
%