Что делает оператор Haskell?



прохождение документации Haskell всегда немного больно для меня, потому что вся информация, которую вы получаете о функции, часто не более чем: f a -> f [a] что может означать любое количество вещей.



как и в случае .



все, что мне дано, это:(<|>) :: f a -> f a -> f a и вот это "ассоциативная бинарная операция"...



при осмотре Control.Applicative я узнаю, что он делает, казалось бы, несвязанные вещи, в зависимости от по реализации.



instance Alternative Maybe where
empty = Nothing
Nothing <|> r = r
l <|> _ = l


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



instance Alternative [] where
empty = []
(<|>) = (++)


за исключением того, что здесь он просто вызывает оператор конкатенации списка... Ломая мою идею...



так что же это за функция? Какая от него польза? Где это вписывается в грандиозную схему вещи?

485   4  

4 ответов:

обычно это означает "выбор" или "параллель" в этом a <|> b - Это либо "выбор"a или b или a и b выполняться параллельно. Но давайте вернемся назад.

на самом деле, нет никакого практического смысла в операциях в объявлениях типа (<*>) или (<|>). Эти операции получают значение двумя способами: (1) через законы и (2) через экземпляры. Если мы не говорим о особенности экземпляр Alternative тогда только (1) Доступно для интуитивный смысл.

так что "ассоциативный" означает, что a <|> (b <|> c) это то же самое, что (a <|> b) <|> c. Это полезно, Так как это означает, что мы заботимся только о последовательность вещей, прикованных вместе с (<|>), а не их "дерево".

другие законы включают идентичность с empty. В частности, a <|> empty = empty <|> a = a. В нашей интуиции с "выбором" или "параллелью" эти законы читаются как "A или (что-то невозможное) должно быть"или" a рядом (пустой процесс) - это просто a". Оно указывает, что empty это какой-то" режим отказа " для Alternative.

есть и другие законы, как (<|>)/empty взаимодействовать с fmap (от Functor) или pure/(<*>) (от Applicative), но, пожалуй, лучший способ продвинуться вперед в понимании смысла (<|>) это изучить очень распространенный пример типа, который создает экземпляры Alternative: a Parser.

если x :: Parser A и y :: Parser B затем (,) <$> x <*> y :: Parser (A, B) анализ xа то y в последовательности. В отличие от этого, (fmap Left x) <|> (fmap Right y) анализ илиx или y, начиная с x, чтобы попробовать оба возможных разбора. Другими словами, это указывает на филиала в вашем дереве разбора, выбор или параллельный разбор Вселенной.

(<|>) :: f a -> f a -> f a на самом деле говорит вам, довольно много, даже без учета законов Alternative.

это занимает два f a значения, и должен дать один обратно. Поэтому ему придется как-то комбинировать или выбирать из своих входов. Это полиморфный тип a, Так что он будет совершенно не в состоянии проверить все значения типа a может быть внутри f a; это означает, что она не могу сделать "объединение" путем объединения a значения, поэтому он должен к нему чисто в термины любой структуры конструктора типа f добавляет.

имя тоже немного помогает. Какое-то" или "- это действительно расплывчатое понятие, которое авторы пытались обозначить именем" Альтернатива "и символом"".

теперь, если у меня есть два Maybe a значения и я должен объединить их, что я могу сделать? Если они оба Nothing Я есть вернуться Nothing для создания a. Если хотя бы один из них-это Just ... я могу вернуться один из моих входов как есть, или я могу вернуть Nothing. Есть очень мало функций, которые даже возможно С типом Maybe a -> Maybe a -> Maybe a, и для класса, чье имя является "альтернативным", данное довольно разумно и очевидно.

как насчет объединения двух [a] значения? Здесь больше возможных функций, но на самом деле это довольно очевидно, что это может сделать. И название "альтернатива" дает вам хороший намек на то, что это, вероятно, будет предоставил вы знакомы со стандартной интерпретацией" недетерминизма " списка монад/аппликативных; если вы видите [a] как "недетерминированные a" С набором возможных значений, то очевидный путь для "объединения двух недетерминированных a значения "таким образом, что может заслуживать название "альтернатива", чтобы произвести недетерминированный a которое может быть любым из значений с любого из входов.

и для парсеров; объединение двух Парсеры имеют две очевидные широкие интерпретации, которые приходят на ум; либо вы создаете парсер, который будет соответствовать тому, что делает первый, а затем то, что делает второй, или вы создаете парсер, который соответствует или что делает первая или что делает второй (есть, конечно, тонкие детали каждого из этих вариантов, которые оставляют место для вариантов). Учитывая название "альтернатива", интерпретация " или " кажется очень естественной для <|>.

так, видно из достаточно высокий уровень абстракции, эти операции do все "делают то же самое". Класс type действительно предназначен для работы на том высоком уровне абстракции, где все эти вещи "выглядят одинаково". Когда я работаю на одном известном экземпляре, я просто думаю о <|> операции, а именно то, что он делает для этого конкретного типа.

интересный пример Alternative Это не парсер или MonadPlus-как вещь Concurrently, очень полезный тип от async пакета.

на Concurrently,empty - это вычисление, которое продолжается вечно. И (<|>) выполняет свои аргументы одновременно, возвращает результат первого, который завершает, и отменяет другой.

эти кажется очень разные, но считаю:

Nothing <|> Nothing == Nothing
     [] <|>      [] ==      []

Just a  <|> Nothing == Just a
    [a] <|>      [] ==     [a]

Nothing <|> Just b  == Just b
     [] <|>     [b] ==     [b]

Так... это на самом деле очень, очень как, даже если реализация выглядит по-разному. Единственное реальное различие здесь:

Just a  <|> Just b  == Just a
    [a] <|>     [b] ==     [a, b]

A Maybe может содержать только один значение (или ноль, но не любой другой суммы). Но эй, если бы они оба были одинаковых, зачем вам нужны два разных типа? Все дело в том, что они разные, вы знаете, быть разными.

В целом,реализация может выглядеть совершенно по-другому, но на самом деле они очень похожи.

Comments

    Ничего не найдено.