我正在寻找一种非常通用的解决方案。我的目标是找到一种干净的方式来对点(坐标)进行操作,无论是2D还是3D。我的数据Point是Num的一个实例,它提供了执行基础数学运算的函数。
data Point = Point2D Float Float
| Point3D Float Float Float deriving Show
add :: Point -> Point -> Point
add (Point2D xa ya) (Point2D xb yb) = Point2D (xa+xb) (ya+yb)
add (Point3D xa ya za) (Point3D xb yb zb) = Point3D (xa+xb) (ya+yb) (za+zb)
divT (Point2D x y) v = Point2D (x / v) (y / v)
divT (Point3D x y z) v = Point3D (x / v) (y / v) (z / v)
fromIntegerP :: Integer -> Point
fromIntegerP v = Point2D (fromIntegral v) 0
--fromIntegerP v = Point3D (fromIntegral v) 0 0
instance Num Point where
(+) = add
fromInteger = fromIntegerP
p2D1 = Point2D 1.0 2.0
p2D2 = Point2D 4.0 5.0
p3D1 = Point3D 1.0 2.0 3.0
p3D2 = Point3D 6.0 6.0 6.0
main = do
putStrLn . show $ sum [p2D1,p2D2]
putStrLn . show $ sum [p3D1,p3D2]
此代码输出:
Point2D 5.0 7.0
*** Exception: pointStackoverflow.hs:(5,1)-(6,75): Non-exhaustive patterns in function add
...因为每个Point.fromInteger都会产生一个Point2D,即使我们期望一个Point3D。我想在“实例Num Point”中说一个方法,如果需要Point2D那么fromInteger是fromIntegerToPoint2D else fromIntegerToPoint3D。但我不知道如何根据返回类型做出选择。
任何提示?谢谢
答案 0 :(得分:2)
您希望Point2D
和Point3D
为不同的类型,而不是相同类型的不同构造函数。
从此开始并填写定义:
data Point2D = Point2D Float Float
data Point3D = Point3D Float Float Float
instance Num Point2D where
fromInteger = ...
(+) = ...
instance Num Point3D where
fromInteger = ...
(+) = ...
答案 1 :(得分:0)
这是一个解决方案:
class Point a where
add :: a -> a -> a
fromIntegerP :: Integer -> a
data Point2D = Point2D Float Float deriving Show
data Point3D = Point3D Float Float Float deriving Show
instance Point Point2D where
add (Point2D xa ya) (Point2D xb yb) = Point2D (xa+xb) (ya+yb)
fromIntegerP v = Point2D (fromIntegral v) 0
instance Point Point3D where
add (Point3D xa ya za) (Point3D xb yb zb) = Point3D (xa+xb) (ya+yb) (za+zb)
fromIntegerP v = Point3D (fromIntegral v) 0 0
instance Num Point2D where
(+) = add
fromInteger = fromIntegerP
instance Num Point3D where
(+) = add
fromInteger = fromIntegerP
p2D1 = Point2D 1.0 2.0
p2D2 = Point2D 4.0 5.0
p3D1 = Point3D 1.0 2.0 3.0
p3D2 = Point3D 6.0 6.0 6.0
main = do
putStrLn . show $ sum [p2D1,p2D2]
putStrLn . show $ sum [p3D1,p3D2]
我仍在寻找改进措施(instance Num Point2D where
和instance Num Point3D where
),但它确实有效!