Haskell:模式与自定义数据类型匹配

时间:2019-07-08 01:37:35

标签: haskell functional-programming pattern-matching

我具有以下自定义数据类型:

type Length = Integer 
type Rotation = Integer 
data Colour = Colour { red, green, blue, alpha :: Int }
            deriving (Show, Eq)

data Special 
  = L Length 
  | R Rotation
  | Col Colour  
  deriving (Show, Eq) 

说我有以下形式的元组:

let x = ("Jump", R 90)

然后我使用以下命令在元组中提取第二个值:

snd x = R 90

有什么方法可以使用模式匹配从R 90中获取Rotation值90,以便可以在其他代码区域中使用它?当我使用snd x时,结果的类型为Special类型,但是我只想获取Rotation值。任何见解都会受到赞赏。

2 个答案:

答案 0 :(得分:5)

RSpecial数据类型的构造函数。为了从Rotation中提取R,您需要编写以下函数:

unsafeExtractRotation :: Special -> Rotation
unsafeExtractRotation (R rotation) = rotation

但是,此函数是 unsafe (顾名思义),因为它是部分函数:不能处理所有情况。根据函数类型,它应该与Special数据类型的任何值一起使用,因此可以将L构造函数传递给此函数,它将崩溃,后来可能非常崩溃。找出此类错误的来源很困难。

更安全的功能如下所示:

extractRotation :: Special -> Maybe Rotation
extractRotation (R rotation) = Just rotation
extractRotation _ = Nothing

它不会崩溃。相反,它会强制您明确处理通过其他构造函数的情况。

答案 1 :(得分:1)

根据您提供的信息,我可以提出三个想法,一个来自Shersh,但您可以使用一个更适合您的代码的想法:

-- If is not of Rotation type, value is 0
specialToRotation (R n) = n
specialToRotation _     = 0

-- If not of Rotation type, pattern matching failure
specialToRotation2 (R n) = n

-- If not of Rotation type, value is Nothing

specialToRotation3 (R n) = Just n
specialToRotation3 _     = Nothing

选项2)并非完全错误,Haskell中有很多功能是局部的,请从列表api的headtail中考虑。两者都没有空列表的定义。所以也许您可以使用它。