計算機科学のブログ

型によるプログラミング 直積型と直和型 ブックストアの商品の拡張

入門Haskellプログラミング (Will Kurt(著)、株式会社クイープ(監修、翻訳)、翔泳社)のUNIT3(型によるプログラミング)、LESSON 16(直積型と直和型)、16.5(練習問題)Q16-1の解答を求めてみる。

コード

lesson/app/Main.hs

module Main where

import Lib
  ( items,
  )

main :: IO ()
main = do
  mapM_ print items

lesson/src/Lib.hs

module Lib
  ( items,
  )
where

items :: [(String, Double)]
items = zip creators prices

storeItems :: [StoreItem]
storeItems =
  [ BookItem $
      Book
        { author = AuthorCreator $ Author $ Name "firstName" "lastName",
          bookPrice = 10
        },
    RecordItem $
      VinylRecord
        { artist =
            ArtistCreator $
              Person $
                NameWithMiddle "firstName" "middleName" "lastName",
          recordPrice = 20
        },
    ToyItem $
      CollectibleToy
        { name = "toy",
          toyPrice = 30
        },
    PamphletItem $
      Pamphlet
        { title = "Title",
          description = "Description",
          email = "haskell@example.com"
        }
  ]

creators :: [String]
creators = map madeBy storeItems

prices :: [Double]
prices = map price storeItems

type FirstName = String

type LastName = String

type MiddleName = String

data Name
  = Name FirstName LastName
  | NameWithMiddle FirstName MiddleName LastName
  | TwoInitialsWithLast Char Char LastName
  deriving (Show)

data Author = Author Name deriving (Show)

data Artist = Person Name | Band String deriving (Show)

data Creator
  = AuthorCreator Author
  | ArtistCreator Artist
  deriving (Show)

data Book = Book
  { author :: Creator,
    bookPrice :: Double
  }

data VinylRecord = VinylRecord
  { artist :: Creator,
    recordPrice :: Double
  }

data CollectibleToy = CollectibleToy
  { name :: String,
    toyPrice :: Double
  }

data Pamphlet = Pamphlet
  { title :: String,
    description :: String,
    email :: String
  }

data StoreItem
  = BookItem Book
  | RecordItem VinylRecord
  | ToyItem CollectibleToy
  | PamphletItem Pamphlet

price :: StoreItem -> Double
price (BookItem book) = bookPrice book
price (RecordItem record) = recordPrice record
price (ToyItem toy) = toyPrice toy
price (PamphletItem _) = 0

madeBy :: StoreItem -> String
madeBy (BookItem book) = show $ author book
madeBy (RecordItem vinylRecord) = show $ artist vinylRecord
madeBy (PamphletItem pamphlet) = title pamphlet
madeBy _ = "unknown"

入出力結果(Terminal, Zsh)

% stack exec lesson-exe
("AuthorCreator (Author (Name \"firstName\" \"lastName\"))",10.0)
("ArtistCreator (Person (NameWithMiddle \"firstName\" \"middleName\" \"lastName\"))",20.0)
("unknown",30.0)
("Title",0.0)
%