計算機科学のブログ

コンテキストでの型の操作 Monad型クラス do表記を使ってMonadを扱いやすくする Monad型に対応、リファクタリング

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

コード

type Pizza = (Double, Double)

areaGivenDiameter :: Double -> Double
areaGivenDiameter size = pi * (size / 2) ^ 2

costPerInch :: Pizza -> Double
costPerInch (size, cost) = cost / areaGivenDiameter size

comparePizzas :: Pizza -> Pizza -> Pizza
comparePizzas p1 p2 =
  ( \costP1 costP2 ->
      if costP1 < costP2
        then p1
        else p2
  )
    (costPerInch p1)
    (costPerInch p2)

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

costData :: [Double]
costData = [18.0, 16.0]

sizeData :: [Double]
sizeData = [20.0, 15.0]

monadMain :: Monad m => m Double -> m Double -> m String
monadMain sizeData costData = do
  size1 <- sizeData
  cost1 <- costData
  size2 <- sizeData
  cost2 <- costData
  let pizza1 = (size1, cost1)
  let pizza2 = (size2, cost2)
  let betterPizza = comparePizzas pizza1 pizza2
  return $ describePizza betterPizza

xs :: [String]
xs = monadMain sizeData costData

ys :: [Maybe String]
ys =
  [ monadMain (Just 2) (Just 3),
    monadMain Nothing $ Just 4
  ]

main :: IO ()
main = do
  print xs
  mapM_ print xs
  print ys
  mapM_ print ys

入出力結果(Terminal, Zsh)

% runghc sample3.hs
["The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch","The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 15.0 pizza is cheaper at 0.10185916357881301 per square inch","The 15.0 pizza is cheaper at 9.054147873672269e-2 per square inch","The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch","The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch","The 15.0 pizza is cheaper at 9.054147873672269e-2 per square inch","The 15.0 pizza is cheaper at 9.054147873672269e-2 per square inch"]
"The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch"
"The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 15.0 pizza is cheaper at 0.10185916357881301 per square inch"
"The 15.0 pizza is cheaper at 9.054147873672269e-2 per square inch"
"The 20.0 pizza is cheaper at 5.729577951308232e-2 per square inch"
"The 20.0 pizza is cheaper at 5.092958178940651e-2 per square inch"
"The 15.0 pizza is cheaper at 9.054147873672269e-2 per square inch"
"The 15.0 pizza is cheaper at 9.054147873672269e-2 per square inch"
[Just "The 2.0 pizza is cheaper at 0.954929658551372 per square inch",Nothing]
Just "The 2.0 pizza is cheaper at 0.954929658551372 per square inch"
Nothing
%