Сопоставление с образцом инфикса - PullRequest
1 голос
/ 08 января 2020

Проблема, с которой я иногда сталкиваюсь при программировании на Haskell, заключается в том, что иногда я хочу сопоставить шаблон со значением, но меня интересует только информация истина-ложь о том, соответствует ли значение шаблону (например, спецификация c конструктор типа данных). Например:

data Color = 
    RGB Int Int Int 
  | Greyscale Int

toHex :: Color -> String
toHex color =
  if isGreyscale color then something
  else somethingElse

  where
  isGreyscale :: Color -> Bool
  isGreyscale (Greyscale _) = True
  isGreyscale _             = False

, тогда как я хотел бы сделать сопоставление с образцом без создания ненужной вспомогательной функции, что-то вроде:

toHex :: Color -> String
toHex color =
  if (color ~~ (Greyscale _)) then something
  else somethingElse

Есть ли специфика c синтаксис, разрешающий что-то похожее на пример выше? Или, может быть, идиома, которая может пригодиться в таких ситуациях?

Ответы [ 3 ]

4 голосов
/ 08 января 2020

Я не верю, что есть (или может быть) инфиксный оператор, потому что шаблон не является значением; это синтаксис.

Вы ищете case выражение

toHex :: Color -> String
toHex color = case color of
               Greyscale _ -> something
               otherwise -> somethingElse

, хотя вы бы чаще писали это как

toHex :: Color -> String
toHex (Greyscale _) = something
toHex _ = somethingElse

, которое, по сути, не относится к коду выше.

В GH C также есть расширение LambdaCase, которое позволит вам написать следующее, исключив ненужную в противном случае переменную color.

{-# LANGUAGE LambdaCase #-}


toHex :: Color -> String
toHex = \case 
          Greyscale _ -> something
          otherwise -> somethingElse
2 голосов
/ 08 января 2020

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

toHex :: Color -> String
toHex (Greyscale _) = something
toHex _ = somethingElse

Первый шаблон соответствует значению серой шкалы независимо от целочисленного значения, а второе предложение соответствует всему остальному. Если something и somethingElse являются функциями, которые требуют подробностей из параметра, вы можете легко их зафиксировать:

toHex :: Color -> String
toHex (Greyscale g) = something g
toHex (RGB r g b) = somethingElse r g b
1 голос
/ 09 января 2020

Вы можете использовать многофакторные if-выражения и шаблонные охранники, чтобы получить почти тот синтаксис, который вам нужен:

{-# LANGUAGE MultiWayIf #-}

toHex :: Color -> String
toHex color =
  if | Greyscale _ <- color -> something
     | otherwise -> somethingElse
...