简体   繁体   中英

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? When I use snd x , the type of the result is of type Special but I would just like to get the Rotation value. Any insights are appreciated.

R is a constructor of the Special data type. In order to extract Rotation from R you need to write the following function:

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.

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:

-- 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. Both has no definition for empty list. So maybe you could use it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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