Сопоставление с образцом в выражении, которому позволяют,

Как Вы извлекаете значение из переменной неизвестного конструктора?

Например, я хотел бы инвертировать значение в Также, если бы был создан как Право:

let Right x = getValue
in Right (negate x)

Этот код успешно связывает значение Права (Интервал в этом случае) к x.

Это работает, но что, если getValue возвращает Левое вместо этого? Существует ли способ определить тип переменной в выражении, которому позволяют? Или есть ли лучший способ приблизиться к этой проблеме?

11
задан Don Stewart 19 April 2011 в 03:12
поделиться

2 ответа

В общем, вы можете сделать следующее:

case getValue of
  Right x -> Right $ negate x
  e       -> e

Что это делает, должно быть понятно: это просто как сопоставление шаблонов в аргументе функции, но по значению. Чтобы сделать то, что вам нужно, у вас есть вариант по умолчанию, который отлавливает все, что не совпало, а затем возвращает это.

В вашем конкретном случае, однако, вы можете сделать кое-что более приятное:

negate `fmap` getValue

Или, с import Control.Applicative, вы можете использовать <$> как синоним fmap (negate <$> getValue). Функция fmap имеет тип fmap :: Functor f => (a -> b) -> f a -> f b. Для любого функтора1, fmap преобразует функцию на обычных значениях в функцию внутри функтора. Например, списки являются функтором, и для списков fmap = map. Здесь Either e представляет собой вектор, который является либо исключением Left e, либо значением Right a; применение функции к Left ничего не делает, но применение функции к Right применяет ее внутри Right. Другими словами,

instance Functor (Either e) where
  fmap _ (Left l)  = Left l
  fmap f (Right r) = Right $ f r

Таким образом, версия case является прямым ответом на ваш вопрос, но ваш конкретный пример лучше аппроксимируется fmap.

1: В первом приближении, функторы - это "контейнеры". Если вы плохо ориентируетесь в различных классах типов, я рекомендую Typeclassopedia в качестве исчерпывающего справочника; есть еще много учебников, и лучший способ получить представление о них - просто поиграть с ними. Однако, fmap для конкретных типов часто легко использовать (особенно, на мой взгляд, когда написано <$>).

18
ответ дан 3 December 2019 в 05:56
поделиться

Ответьте на заголовок этого вопроса:
Я не вижу большой разницы между « ... где » и « впускаем ... ». Оба позволяют объявить несколько случаев привязки аргументов функции:

f val = let negR (Right x) = Right (negate x)
            negR y = y
        in negR val

или let {negR (Right x) = Right (отрицать x); negR y = y; } in negR val

2
ответ дан 3 December 2019 в 05:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: