Монадический эквивалент аппликативного падежа ‹*

Прочитав ответ Энтони на вопрос синтаксического анализатора, связанный со стилем, я пытался убедить себя, что написание монадических синтаксических анализаторов все еще может быть довольно компактным.

Итак, вместо

reference :: Parser Transc
reference = try $ do string "#{"
                     a <- number
                     char ','
                     b <- number
                     char ','
                     c <- number
                     char '}'
                     return $ Outside (a,b,c)

Мы можем просто иметь:

reference3 :: Parser Transc
reference3 = liftM3 (((Outside .).) .  (,,)) 
             (string "#{" >> number <<! char ',') 
             number
             (char ',' >> number <<! char '}') where 
               (<<!) = liftM2 const

Что очень похоже на аппликативную версию, предоставленную Энтони:

reference2 :: Parser Transc
reference2 = ((Outside .) .) . (,,) 
             <$> (string "#{" *> number2 <* char ',') 
             <*> number2 
             <*> (char ',' *> number2 <* char '}')

... за исключением оператора <<!, который концептуально подобен <*, который определяется как liftA2 const, означающий «последовательность, но отбрасывание значения и использование значения, предоставленного слева».

Конечно, ‹‹ было бы плохим именем для liftM2 const, это предполагало бы, что << эквивалентно flip >>, если мы следуем той же логике, что и >>= и =<<.

Я не нахожу "liftM2 const" под одним именем. Это потому, что это не настолько полезно?


person gawi    schedule 24.10.2011    source источник
comment
Независимо от того, почему ваш конструктор Outside принимает тройку, а не три аргумента? Последнее сделает ваш код более приятным.   -  person augustss    schedule 24.10.2011
comment
@augustss Это не мое. Я просто взял пример из чужого поста. Согласен, что форма карри была бы лучше.   -  person gawi    schedule 24.10.2011


Ответы (1)


Я не совсем вижу проблему. Каждая монада также является аппликативным функтором, поэтому вы можете просто использовать (*>) и в монадических выражениях.

(Во время этого ответа (2011 год) Applicative не был надклассом Monad, поэтому, возможно, было необходимо добавить соответствующий экземпляр класса.)

person Heinrich Apfelmus    schedule 24.10.2011
comment
Иными словами, что даст вам аналогичный оператор, тип которого ограничен Monad? Эти операторы предназначены для статического указания потока вычислений, для чего и нужны операторы Applicative. - person Anthony; 24.10.2011
comment
Хорошо, думаю, я понял. Корень проблемы в том, что Applicative не является суперклассом Monad (к сожалению!). Но пытаться перенести все аппликативные функции и операторы в монаду — глупое занятие. Гораздо проще добавить экземпляр Applicative и, следовательно, получить выгоду от более общей абстракции. - person gawi; 24.10.2011
comment
@gawi: По сути, <<! будет просто новым именем для уже существующей функции (а именно <*). Просто последняя функция на самом деле не существует по какой-то очень скучной причине (а именно, что Applicative не является суперклассом Monad). - person Heinrich Apfelmus; 24.10.2011
comment
@Heinrich Apfelmus Но у нас есть <*> и ap, pure и return, *> и >>. Однако <* — единственная функция Applicative, не имеющая монадического эквивалента. Я могу жить с этим, но мне просто интересно. - person gawi; 24.10.2011
comment
@HeinrichApfelmus По историческим причинам Applicative не является суперклассом Monad [...] Возможно, вы захотите обновить свой ответ, теперь, когда действует предложение Functor-Applicative-Monad. - person jub0bs; 06.09.2015