我目前正在 Haskell 中使用 ADT,并尝试构建一个 ADT Figure
:
data Figure = Rect { x :: Integer, y :: Integer, width :: Integer, height :: Integer}
| Circle { x :: Integer, y :: Integer, radius :: Integer}
| CombiFigure Figure Figure
deriving (Eq, Show, Read)
现在我遇到了如何实现一个不应该接受每个
Figure
的函数的问题。 ,但例如只有一个 Circle
.我已经有一个糟糕的设计了吗?或者是否有一些最佳实践如何做到这一点?
例如,考虑一个直径函数。我想到的所有(我是 Haskell 的完全初学者)是以下两个选项,使用
undefined
或 Maybe
:1:
diameter :: Figure -> Integer
diameter (Circle _ _ r) = 2 * r
diameter _ = undefined
2:
diameter :: Figure -> Maybe Integer
diameter (Circle _ _ r) = Just (2 * r)
diameter _ = Nothing
有没有更可取的方法来实现这一目标?
谢谢!
最佳答案
你说得对,这里有些不对劲。最好的思考方式是从函数 diameter
开始。并决定理想情况下它的类型应该是什么。你可能会想出
diameter :: Circle -> Integer
diameter (Circle _ _ r) = 2 * r
因为直径只为圆定义。
这意味着您必须通过拆分 Circle(以及 Rect)来扩充数据结构:
data Figure = RectFigure Rect
| CircleFigure Circle
| CombiFigure Figure Figure
deriving (Eq, Show, Read)
data Rect = Rect { rectX :: Integer, rectY :: Integer, rectWidth :: Integer, height :: Integer}
deriving (Eq, Show, Read)
data Circle = Circle { circleX :: Integer, circleY :: Integer, circleRadius :: Integer}
deriving (Eq, Show, Read)
这很好,因为它现在更灵活:您可以编写不关心什么的函数
Figure
它们适用于,您可以编写在特定 Figure
上定义的函数s。现在,如果我们在一个更高级的函数中并且有一个对
Figure
的引用。我们想计算它的 diameter
如果是 CircleFigure
,那么您可以使用模式匹配来做到这一点。注意:使用
undefined
或异常(在纯代码中)可能是代码异味。它可能可以通过重新考虑您的类型来解决。如果必须指示失败,请使用 Maybe
/Either
.
关于haskell - 如何使函数仅可用于 ADT 的某个数据构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34964015/