Haskell: сопоставление шаблонов с пользовательскими типами данных - PullRequest
1 голос
/ 08 июля 2019

У меня есть следующий тип данных:

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

Есть ли способ использовать сопоставление с образцом, чтобы получить значение поворота 90 из R 90, чтобы я мог использовать его в другой области кода? Когда я использую snd x, тип результата имеет тип Special, но я просто хотел бы получить значение Rotation. Любые идеи приветствуются.

Ответы [ 2 ]

5 голосов
/ 08 июля 2019

R является конструктором типа данных Special. Чтобы извлечь Rotation из R, вам нужно написать следующую функцию:

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

Однако эта функция небезопасна (как следует из ее названия), потому что она является частичной: она не обрабатывает все случаи. В соответствии с типом функции, он должен работать с любым значением типа данных Special, так что в эту функцию можно передать конструктор L, и он потерпит крах, а затем в будущем выяснить это может быть очень проблематично. источник такой ошибки.

Более безопасная функция может выглядеть так:

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

Это не сломается. Вместо этого он заставляет вас явно иметь дело со случаями, когда вы передали другой конструктор.

1 голос
/ 08 июля 2019

С информацией, которую вы предоставили, я могу предложить три идеи, одну из 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 являются частичными, подумайте в head и tail из списка API.У обоих нет определения пустого списка.Так что, может быть, вы могли бы использовать его.

...