3
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

【解答例】Haskell 代数的データ型 超入門

Haskell 代数的データ型 超入門の解答例です。

列挙型

【問1】光の三原色と、2つの色を混合する関数mixを定義してください。混ぜることによってできる色も定義の対象とします。ただし同じ成分同士は強め合わないものとします。

条件を列挙します。逆の組み合わせを一括処理しているのがポイントです。

data Color = Blue | Red | Magenta | Green | Cyan | Yellow | White
    deriving (Show, Eq)

mix Blue    Red       = Magenta
mix Blue    Magenta   = Magenta
mix Blue    Green     = Cyan
mix Blue    Cyan      = Cyan
mix Blue    Yellow    = White
mix Red     Magenta   = Magenta
mix Red     Green     = Yellow
mix Red     Cyan      = White
mix Red     Yellow    = Yellow
mix Magenta Green     = White
mix Magenta Cyan      = White
mix Magenta Yellow    = White
mix Green   Cyan      = Cyan
mix Green   Yellow    = Yellow
mix Cyan    Yellow    = White
mix White   _         = White
mix c1 c2 | c1 == c2  = c1
          | otherwise = mix c2 c1

main = do
    print $ mix Blue Blue
    print $ mix Red Blue
    print $ mix Red $ mix Blue Green
実行結果
Blue
Magenta
White

別解

ビット演算で簡単に書けます。

import Data.Bits

data Color = Black | Blue | Red | Magenta | Green | Cyan | Yellow | White
    deriving (Show, Enum)

mix c1 c2 = toEnum (fromEnum c1 .|. fromEnum c2) :: Color

main = do
    print $ mix Red Blue
    print $ mix Red $ mix Blue Green
実行結果
Magenta
White

直積型

【問2】x,y,w,hを表現したRect型を定義して、RectPointが含まれるかどうかを判定する関数containsを実装してください。

data Point = Point Int Int deriving Show
data Rect = Rect Int Int Int Int deriving Show

contains (Rect x y w h) (Point px py) =
    x <= px && px < x + w && y <= py && py < y + h

main = do
    print $ contains (Rect 2 2 3 3) (Point 1 1)
    print $ contains (Rect 2 2 3 3) (Point 2 2)
    print $ contains (Rect 2 2 3 3) (Point 3 3)
    print $ contains (Rect 2 2 3 3) (Point 4 4)
    print $ contains (Rect 2 2 3 3) (Point 5 5)
実行結果
False
True
True
True
False

直和型

【問3】RectPointを2次元と3次元の両方に対応させて、問2のcontainsも対応させてください。

data Point = Point   Int Int
           | Point3D Int Int Int
           deriving Show

data Rect = Rect   Int Int Int Int
          | Rect3D Int Int Int Int Int Int
          deriving Show

contains (Rect x y w h) (Point px py) =
    x <= px && px < x + w && y <= py && py < y + h

contains (Rect3D x y z w h d) (Point3D px py pz) =
    x <= px && px < x + w &&
    y <= py && py < y + h &&
    z <= pz && pz < z + d

main = do
    print $ contains (Rect 2 2 3 3) (Point 1 1)
    print $ contains (Rect 2 2 3 3) (Point 2 2)
    print $ contains (Rect 2 2 3 3) (Point 3 3)
    print $ contains (Rect 2 2 3 3) (Point 4 4)
    print $ contains (Rect 2 2 3 3) (Point 5 5)
    print $ contains (Rect3D 2 2 2 3 3 3) (Point3D 1 1 1)
    print $ contains (Rect3D 2 2 2 3 3 3) (Point3D 2 2 2)
    print $ contains (Rect3D 2 2 2 3 3 3) (Point3D 3 3 3)
    print $ contains (Rect3D 2 2 2 3 3 3) (Point3D 4 4 4)
    print $ contains (Rect3D 2 2 2 3 3 3) (Point3D 5 5 5)
実行結果
False
True
True
True
False
False
True
True
True
False

レコード構文

【問4】問2の解答をレコード構文で書き直してください。

data Point = Point { px :: Int, py :: Int } deriving Show
data Rect  = Rect  { rx :: Int, ry :: Int, rw :: Int, rh :: Int } deriving Show

contains r p =
    (rx r) <= (px p) && (px p) < (rx r) + (rw r) &&
    (ry r) <= (py p) && (py p) < (ry r) + (rh r)

main = do
    print $ contains Rect { rx = 2, ry = 2, rw = 3, rh = 3 } Point { px = 1, py = 1 }
    print $ contains Rect { rx = 2, ry = 2, rw = 3, rh = 3 } Point { px = 2, py = 2 }
    print $ contains Rect { rx = 2, ry = 2, rw = 3, rh = 3 } Point { px = 3, py = 3 }
    print $ contains Rect { rx = 2, ry = 2, rw = 3, rh = 3 } Point { px = 4, py = 4 }
    print $ contains Rect { rx = 2, ry = 2, rw = 3, rh = 3 } Point { px = 5, py = 5 }
実行結果
False
True
True
True
False
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
3
Help us understand the problem. What are the problem?