假设我有像data Shape = Circle Size | Rectangle Corner和Size这样的数据类型,Corner也是不同的数据类型,比如data Size = Big | Small deriving (Show, Eq, Ord)和data Corner = Blunt | Sharp Size deriving (Show, Eq, Ord)。
我想编写一个返回Big而不是Circle Big的函数。最好的方法是什么?
发布于 2021-05-29 17:38:18
我估计您需要一个提取形状的主属性的函数,所以如下所示:
> getAttr (Circle Big)
Big
> getAttr (Rectangle Blunt)
Blunt
> getAttr (Rectangle (Sharp Small))
Sharp Small从技术上讲这是可能的。您可以编写一个类型类:
class GetAttr a where
getAttr :: Shape -> a
instance GetAttr Size where
getAttr (Circle s) = s
instance GetAttr Corner where
getAttr (Rectangle c) = c要定义这样的函数,必须帮助GHCi处理以下类型:
λ> getAttr (Circle Big) :: Size
Big
λ> getAttr (Rectangle Blunt) :: Corner
Blunt
λ> getAttr (Rectangle (Sharp Small)) :: Corner
Sharp Small如果您请求错误的类型,您将得到一个运行时错误:
λ> getAttr (Rectangle Blunt) :: Size
*** Exception: OneAttribute.hs:9:3-24: Non-exhaustive patterns in function getAttr因此,它可能是返回一个Maybe:
class GetAttr a where
getAttr :: Shape -> Maybe a
instance GetAttr Size where
getAttr (Circle s) = Just s
getAttr _ = Nothing
instance GetAttr Corner where
getAttr (Rectangle c) = Just c
getAttr _ = Nothing给予:
λ> getAttr (Rectangle Blunt) :: Maybe Corner
Just Blunt
λ> getAttr (Rectangle Blunt) :: Maybe Size
Nothing但是,既然您有了这个函数,通常您会发现它并不是很有用。几乎每次使用它时,您都会发现您已经确切地知道了所期望的属性类型是Size还是Corner,因此您可以用更简单、更清晰的函数替换getAttr:
getSize :: Shape -> Maybe Size
getSize (Circle s) = Just s
getSize _ = Nothing
getCorner :: Shape -> Maybe Corner
getCorner (Rectangle c) = Just c
getCorner _ = Nothing或者完全放弃这些函数,当您发现自己需要提取形状的主要属性时,直接在Shape上进行案例匹配:
printAttribute :: Shape -> String
printAttribute (Circle s) = "shape: " ++ show s
printAttribute (Rectangle c) = "corner: " ++ show chttps://stackoverflow.com/questions/67732436
复制相似问题