「独自の型と型クラスの作成」では、次のコードを提供します。
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)
surface :: Shape -> Float
surface (Circle _ r) = pi * r ^ 2
surface (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
nudge :: Shape -> Float -> Float -> Shape
nudge (Circle (Point x y) r) a b = Circle (Point (x+a) (y+b)) r
nudge (Rectangle (Point x1 y1) (Point x2 y2)) a b = Rectangle (Point (x1+a) (y1+b)) (Point (x2+a) (y2+b))
main = do
print (surface (Circle (Point 0 0) 24))
print (nudge (Circle (Point 34 34) 10) 5 10)
現状では、コンストラクターに対するパターンマッチングは、その時点でかなり雑然としています。
nudge (Rectangle (Point x1 y1) (Point x2 y2)) a b = ....
Shapeタイプを次のように定義しましたか?
data Shape = Circle Point Float | Rectangle Float Float Float Float deriving (Show)
次に、タイプの性質が少しわかりにくくなりますが、以下に示すように、パッテンのマッチングはあまり乱雑に見えません。
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Float Float Float Float deriving (Show)
surface :: Shape -> Float
surface (Circle _ r) = pi * r ^ 2
surface (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)
nudge :: Shape -> Float -> Float -> Shape
nudge (Circle (Point x y) r) a b = Circle (Point (x+a) (y+b)) r
nudge (Rectangle x1 y1 x2 y2) a b = Rectangle (x1+a) (y1+b) (x2+a) (y2+b)
main = do
print (surface (Circle (Point 0 0) 24))
print (nudge (Circle (Point 34 34) 10) 5 10)
私の質問は、両方を持つことが可能かどうかです
Rectangle Point Point
と
Rectangle Float Float Float Float
同じコード内(つまり、値コンストラクターの一種の「オーバーロード」)で、次のようなことができます。
...
surface (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs $ y2 - y1)
...
nudge (Rectangle x1 y1 x2 y2) a b = Rectangle (x1+a) (y1+b) (x2+a) (y2+b)
ここで、「...」は上記のコードと同じことを示します。また、「ナッジ(長方形....」ポイントで表記をもう少しコンパクトにするためのトリックは他にありますか?ありがとうございます)。