計算機科学のブログ

Haskell - コンテキストでの型の操作 - do表記を使ってMonadを扱いやすくする - 脱糖, (>>=), (>>)演算子, return, ラムダ式

入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)の UNIT5(コンテキストでの型の操作)、LESSON 31(do表記を使ってMonadを扱いやすくする)、31.4(練習問題)、Q31-1の解答を求めてみる。

コード

sample6.hs

main :: IO ()
main = do
  putStrLn "What is the size of pizza 1"
  size1 <- getLine
  putStrLn "What is the cost of pizza 1"
  cost1 <- getLine
  putStrLn "What is the size of pizza 2"
  size2 <- getLine
  putStrLn "What is the cost of pizza 2"
  cost2 <- getLine
  let pizza1 = (read size1, read cost1)
  let pizza2 = (read size2, read cost2)
  let betterPizza = comparePizzas pizza1 pizza2
  putStrLn (describePizza betterPizza)
  return "What is the size of pizza 1" >>= 
    putStrLn >> 
    getLine >>= 
    (\size1 -> return "What is the cost of pizza 1" >>= 
        putStrLn >> 
        getLine >>=
            (\cost1 -> return "What is the size of pizza 2" >>= 
                putStrLn >> 
                getLine >>=
                    (\size2 -> return "What is the cost of pizza 2" >>= 
                        putStrLn >> 
                        getLine >>=
                            (\cost2 -> return (read size1, read cost1) >>=
                                (\pizza1 -> return (read size2, read cost2) >>=
                                    (\pizza2 -> return (comparePizzas pizza1 pizza2) >>=
                                        (\betterPizza -> return (describePizza betterPizza) >>= 
                                            putStrLn)))))))

areaGivenDiameter :: Double -> Double
areaGivenDiameter size = pi * (size / 2)^2
type Pizza = (Double, Double)
costPerInch :: Pizza -> Double
costPerInch (size, cost) = cost /areaGivenDiameter size
comparePizzas :: Pizza -> Pizza -> Pizza
comparePizzas p1 p2 = if costP1 < costP2
    then p1
    else p2
 where costP1 = costPerInch p1
       costP2 = costPerInch p2

describePizza :: Pizza -> String
describePizza (size, cost) = mconcat ["The ", show size, 
    " pizza is cheaper at ", show costSqInch, " per square inch"]
 where
    costSqInch = costPerInch (size, cost)

入出力結果(Terminal, Zsh)

% runghc sample6.hs
What is the size of pizza 1
2
What is the cost of pizza 1
3
What is the size of pizza 2
3
What is the cost of pizza 2
4
The 3.0 pizza is cheaper at 0.5658842421045168 per square inch
What is the size of pizza 1
2
What is the cost of pizza 1
3
What is the size of pizza 2
3
What is the cost of pizza 2
4
The 3.0 pizza is cheaper at 0.5658842421045168 per square inch
% runghc sample6.hs
What is the size of pizza 1
3
What is the cost of pizza 1
4
What is the size of pizza 2
2
What is the cost of pizza 2
3
The 3.0 pizza is cheaper at 0.5658842421045168 per square inch
What is the size of pizza 1
3
What is the cost of pizza 1
4
What is the size of pizza 2
2
What is the cost of pizza 2
3
The 3.0 pizza is cheaper at 0.5658842421045168 per square inch
%