Haskell `где` с сопоставлением с образцом - PullRequest
3 голосов
/ 23 марта 2020

У меня есть такая функция:

eval :: Expr -> Either ArithmeticError Int
eval (Const a) = Right a
eval (Add a b) = liftM2 (+) ea eb
  where
    ea = eval a
    eb = eval b
eval (Sub a b) = liftM2 (-) ea eb
  where
    ea = eval a
    eb = eval b

Я хотел бы переписать это с одним where использованием. Могу ли я это сделать? Но сопоставление с образцом должно оставаться в этом коде. Спасибо!

1 Ответ

6 голосов
/ 24 марта 2020

Не существует общего, простого способа сопоставления с шаблонами с общими переменными:

foo (Bar a b) = ...
foo (Baz a b) = ...

и последующей записью выражений (в предложениях where или в других местах), таких что a и b соответствуют обе модели одновременно. В Haskell шаблон создает новую область видимости, в которой переменные в шаблоне связаны этим шаблоном, и нет никакого способа «объединить» эти привязки - использование a или b будет либо ссылаются на привязки в Bar a b или Baz a b, но не одновременно.

Самое лучшее, что вы можете сделать, это использовать оператор case для применения общего where предложение для нескольких шаблонов и использование общей вспомогательной функции, которая принимает a и b в качестве аргументов и явно связывает их с общими именами на основе шаблона:

eval :: Expr -> Either ArithmeticError Int
eval e = case e of
  Const a -> Right a
  Add a b -> go (+) a b
  Sub a b -> go (-) a b

  where go op a b = liftM2 op (eval a) (eval b)
...