简体   繁体   English

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

[英]Haskell: Pattern matching with custom data types

I have the following custom data type: 我具有以下自定义数据类型:

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) 

Say that I have a tuple of the following form: 假设我具有以下形式的元组:

let x = ("Jump", R 90)

And I extract the second value in the tuple using: 然后使用以下命令在元组中提取第二个值:

snd x = R 90

Is there any way that I can use pattern matching to get the Rotation value 90 from R 90 so that I can use it in another area of code? 有什么方法可以使用模式匹配从R 90中获得Rotation值90,以便可以在其他代码区域中使用它? When I use snd x , the type of the result is of type Special but I would just like to get the Rotation value. 当我使用snd x ,结果的类型为Special类型,但我只想获取Rotation值。 Any insights are appreciated. 任何见解都表示赞赏。

R is a constructor of the Special data type. RSpecial数据类型的构造函数。 In order to extract Rotation from R you need to write the following function: 为了从R提取Rotation ,您需要编写以下函数:

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

However, this function is unsafe (as its name suggests) because it is partial: it doesn't handle all cases. 但是,此函数是不安全的 (顾名思义),因为它是部分函数:不能处理所有情况。 According to the function type, it should work with any value of the Special data type, so it's possible to pass L constructor to this function, and it will crash and later down the road it can be very problematic to figure out the source of such error. 根据函数类型,它可以与Special数据类型的任何值一起使用,因此可以将L构造函数传递给此函数,并且该函数将崩溃,并在以后的工作中弄清楚此类源代码可能非常成问题。错误。

Safer function can look like this: 更安全的功能如下所示:

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

It won't crash. 它不会崩溃。 Instead, it forces you to deal explicitly with the cases where you passed different constructor. 相反,它迫使您显式处理传递不同构造函数的情况。

With the info you provided, I can come up with three ideas, one from Shersh, but you could use the one that fits more with your code: 利用您提供的信息,我可以提出三个想法,一个来自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

The option 2) is not entirely wrong, a lot of functions are partial in Haskell, think in head and tail from list api. 选项2)并非完全错误,Haskell中有很多功能是部分的,请从列表api的headtail思考。 Both has no definition for empty list. 两者都没有空列表的定义。 So maybe you could use it. 所以也许您可以使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM