Что такое <|> в haskell?

Я все еще изучаю haskell и смотрю snap веб-фреймворк. В их приветственном примере мира есть вещь, которая выглядит как <|>

site :: Snap ()
site =
    ifTop (writeBS "hello world") <|>
    route [ ("foo", writeBS "bar")
          , ("echo/:echoparam", echoHandler)
          ] <|>
    dir "static" (serveDirectory ".")

Google для этого удивительно сложно, и документация snap просто использует <|> как существительное. Что это такое и что он делает?

Ответ 1

Это метод в классе Alternative в модуле Control.Applicative в пакете base.

Обычно это означает, что вы имеете дело с каким-то вычислением, которое может потерпеть неудачу и продолжить. Если оба x и y набраны как m a, где m теги такого рода вычислений, о которых мы говорим, тогда

x <|> y :: m a

- это вычисление, которое "пытается" x, и если оно терпит неудачу, то "пытается" y. Такие экземпляры вычислений составляют Alternative.

Ответ 2

Цитирование оснастки <

Если вы не знакомы с Haskell, вам может быть интересно узнать о & Л; | > . Это просто бинарный оператор, который оценивает свой первый аргумент, и если он не прошел, он оценивает второй. Если первый аргумент преуспел, то он останавливается, не оценивая второй аргумент.

Функция сайта использует &lt | | > для подключения трех различных функций, которые охранять, какая страница отображается. Сначала выполняется функция ifTop. Эта функция выполнена успешно, если запрашиваемый URL-адрес - http://site.com. Если это происходит, затем Snap отправляет ответ "hello world". В противном случае выполняется функция маршрута.

Ответ 3

Я согласен с Xeo в той степени, что &lt | | > имеет эффект игнорирования пустого списка в [] < | > [1,2,3], но под капотом компилятор может конкатенировать пустой список с непустым списком. У меня есть ghci, чтобы автоматически отображать типы распечаток. Вот некоторые результаты, которые предполагают, что в случае списков < | > и ++ могут быть эквивалентными:

λ: [] <|> [3,4]
[3,4]
it :: Num a => [a]
λ: [] ++ [3,4]
[3,4]
it :: Num a => [a]
λ: [1,2] <|> [3,4]
[1,2,3,4]
it :: Num a => [a]
λ: [1,2] ++ [3,4]
[1,2,3,4]
it :: Num a => [a]
λ: :t (<|>) [1,2] [3,4]
(<|>) [1,2] [3,4] :: Num a => [a]
λ: :t (++) [1,2] [3,4]
(++) [1,2] [3,4] :: Num a => [a]
λ: [1,2] <|> [] <|> [3,4]
[1,2,3,4]

Ну, < | > имеет эффект ++ в приведенных выше примерах, но есть больше, чем это происходит. В https://hackage.haskell.org/package/parsec-3.0.0/docs/Text-ParserCombinators-Parsec-Prim.html мы читаем об этом < | > : "Этот комбинатор определен равным члену mplus класса MonadPlus и (Control.Applicative. < | > ) член Control.Applicative.Alternative." Обращаясь к обсуждению Hackage "Control.Monad", мы читаем: mss:: MonadPlus m = > [m a] → m a Источник ", за которым следует" Это обобщает функцию concat на основе списка". Ответ на вопрос "Что делает < | > do?" Коренится в понимании того, что делают компиляторы Haskell, когда они сталкиваются < | > , говорят в "[] < | > [1,2,3]"? Они просто игнорируют []? Выполняют ли они процедуру конкатенации? Есть шаги, связанные с выяснением того, что делать с этим странно перегруженным оператором. Неудивительно, что программисты его озадачивают и соглашаются на то, что знают немного больше, чем эффект от использования его в особых случаях использования.

< | > полезен для выпрыгивания из рекурсивных петель, как только выполняется условие. Вот некоторый код, чтобы предложить, как это работает:

λ: Nothing <|> Just 6 <|> Just 7
Just 6
it :: Num a => Maybe a

λ: Nothing <|> Just [1,2] <|> Nothing <|> Just [3,4]
Just [1,2]
it :: Num t => Maybe [t]