Прочитав ответ Энтони на вопрос синтаксического анализатора, связанный со стилем, я пытался убедить себя, что написание монадических синтаксических анализаторов все еще может быть довольно компактным.
Итак, вместо
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" под одним именем. Это потому, что это не настолько полезно?
Outside
принимает тройку, а не три аргумента? Последнее сделает ваш код более приятным. - person augustss   schedule 24.10.2011