Mar*_*ger 5 haskell pattern-matching algebraic-data-types maybe undefined-function
我目前正在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)
Run Code Online (Sandbox Code Playgroud)
现在我遇到了一个问题,即如何实现一个不应该接受每个函数的函数,Figure例如只有一个函数Circle.
我的设计已经不好了吗?或者有一些最佳实践如何做到这一点?
例如,考虑直径函数.我想到的一切(我是Haskell的初学者)是以下两个选项,使用undefined或Maybe:
1:
diameter :: Figure -> Integer
diameter (Circle _ _ r) = 2 * r
diameter _ = undefined
Run Code Online (Sandbox Code Playgroud)
2:
diameter :: Figure -> Maybe Integer
diameter (Circle _ _ r) = Just (2 * r)
diameter _ = Nothing
Run Code Online (Sandbox Code Playgroud)
是否有更好的方法来实现这一目标?谢谢!
你是对的,这里有些不对劲。考虑它的最好方法是从函数开始diameter并决定它的理想类型应该是什么。你可能会想出
diameter :: Circle -> Integer
diameter (Circle _ _ r) = 2 * r
Run Code Online (Sandbox Code Playgroud)
因为直径仅针对圆定义。
这意味着您必须通过拆分 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)
Run Code Online (Sandbox Code Playgroud)
这很好,因为它现在更加灵活:您可以编写不关心Figure它们应用于什么的函数,并且可以编写在特定 s 上定义的函数Figure。
现在,如果我们在一个更高层的函数中并且有一个对 a 的引用Figure,并且我们想要计算它diameter (如果它是 a )CircleFigure,那么您可以使用模式匹配来执行此操作。
注意:使用undefined或异常(在纯代码中)可能是代码味道。它可能可以通过重新考虑你的类型来解决。如果必须指示失败,请使用Maybe/ Either。