metanohi/site/unhappy/index.md

6.4 KiB

abstract
Rant about Haskell's parser "Happy".

Unhappy About Happy: A Reflection or Something Like That

For the purposes of my quiet rage, this document will be written in all caps. I also will not use proper language. I won't even give suggestions on how to improve Happy; I'll just complain.

STARTING NOW

WHAT HAPPY ???

HAPPY IS PARSER GENERATOR. IT GENERATE HASKELL CODE. VISIT HTTP://WWW.HASKELL.ORG/HAPPY/ FOR UGLY INFO.

HOW HAPPY GOOD

  • EFFICIENT I GUESS
  • WORKS OK
  • PRETTY LOGO

WHY I NOT LIKE HAPPY

JUZT TYPICAL

ONE ERROR IN PARSER.Y GIVE HUGE TYPE ERROR

WHAT IS THIS!

dist/build/l0c/l0c-tmp/Language/L0/Parser/Parser.hs:2452:42:
    Couldn't match type `Value' with `BasicValue -> Value'
    Expected type: HappyAbsSyn
                     (Name, SrcLoc)
                     [(Name,
                       DeclTypeBase Name,
                       [ParamBase Name],
                       ExpBase NoInfo Name,
                       SrcLoc)]
                     (Name,
                      DeclTypeBase Name,
                      [ParamBase Name],
                      ExpBase NoInfo Name,
                      SrcLoc)
                     Uniqueness
                     ([Maybe (DimSize Name)], ElemTypeBase NoInfo Name)
                     (ElemTypeBase NoInfo Name)
                     [TypeBase NoInfo Name]
                     [TypeBase NoInfo Name]
                     [ParamBase Name]
                     (Maybe (CertificatesBase NoInfo Name), [ExpBase NoInfo Name])
                     [ExpBase NoInfo Name]
                     [ExpBase NoInfo Name]
/* ... 200-300 MORE LINES ... */
                        [TupIdentBase NoInfo Name]
                        (TupIdentBase NoInfo Name)
                        (LambdaBase NoInfo Name)
                        (TupleLambdaBase NoInfo Name)
                        (BasicValue -> Value)
                        Int
                        (BasicValue -> Value)
                        (BasicValue -> Value)
                        (BasicValue -> Value)
                        (BasicValue -> Value)
                        (BasicValue -> Value)
                        Value
                        (BasicValue -> Value)
                        (BasicValue -> Value)
                        [Value]
                        [Value]
    In the second argument of `happySpecReduce_3', namely
      `happyReduction_191'
    In the expression: happySpecReduce_3 38# happyReduction_191
    In an equation for `happyReduce_191':
        happyReduce_191 = happySpecReduce_3 38# happyReduction_191

NOT NICE NOT NICE AT ALL

MONADA CAN I HAZ

MAYHAPS U NEED TO PARSE DIFFERENT THAN NORMAL KAY. HOW U THINK. YES: MENTALINCRMENTAL PARSING IT IS

YOU GOT NEED TO PARSE IO GETLINE SOURCES YEAH

PARSE EXPRESSION "2 + 1 *4" OVER MULTI LINES LIKE THIS HERE

WELCOM TO DA FUNKY MULTILINE EXPRESSION PARSER; ENTER UR EXPRESSION
> 2 +
1 *4
TY GOT IT!!  PARSED EXPRESSION IS "2 + 1 * 4" AND U NICE; RESULT IS 6 BTW
>

PARSER SHOULD KNOW "YEAH NOT DUHNE PARSIN YET" WHEN "2 +" READ, SHOULD TEHN READ NEW LINE AND PARSE MORE!

WE CAN PARSE FROM BEGINNING EVERY TIME SURE BUT INEFECICIENT!!!

BUT HOW WE SHOULD / COULD DO THAT SMARTLY I IMPLORE TO LIKE ASK U

YES WE USE CONTINUATION WHICH SMART. LOOK ATTOPARSEC USE CONTINUATION IN RETURN! HTTP://HACKAGE.HASKELL.ORG/PACKAGE/ATTOPARSEC-0.11.1.0/DOCS/DATA-ATTOPARSEC-TEXT.HTML#T:IRESULT

YEAH BUT NOT IN HAPPY............

SO WE MAKE IT MANUAL. WE SPECIFY OWN LEXER AND IMPROVE MONAD. WHEN END OF LINE IS REACH, WE TELL PARSER (FROM INSIDE DA PRASER) DAT DERE IS NO MORE EVER; IF THAT FAILS WE CATCH ERROR (EITHER-LIKE MONAD) AND READ NEW LINE FOR REALS

CLEVER SOLUTION OF US! BUT IN PARSE EXPRESION EXAMPLE ABOV WE USE IO TO GETLINE

WE NOT WANT IO IN ALL PARSING.... EVER EVER!!!!!!!!

HOWTO ABSTRACT IO AWAY? WE WANT TYPE OF EXPORTED FUNCTIONS FROM PARSER TO NOT USE IO AT ALL

SO WE USE WHATEVER MONAD TO GETLINE RIGHT?

class GetLiner m where -- KAY SO m IS MONAD RIGHT
  getSomeLine :: m String

instance GetLiner IO where
  getSomeLine = getLine

WAIT I DONT GET IT

CLASS GETLINER M WHERE -- KAY SO M IS MONAD RIGHT
  GETSOMELINE :: M STRING

INSTANCE GETLINER IO WHERE
  GETSOMELINE = GETLINE

MUCH BETTR. COZ TEHN WE CAN USE

BUT YIAH WE COULD USE TYPE CONSTRAINTS!

LEXER :: GETLINER M => M SOMETHNIG
LEXER = MEHMEHMEH
  WOO <- GETSOMELINE
  MEH MEH

SURE COULD WORK WE NEED JUST TELL HAPPY BOUT IT.

%MONAD { GETLINER M => SOMETHINNG M }

FAILS MISERBLY.................... :-( :( :(

WE ARE LEFT 4 PONDER HOW TO SOLVE! HOWTO ABSTRAKT OUT IO! HOW!!

SOOOO..... WE NEED KINDA CONTINUATIN COMPUTATON MONADY THINGY. I GOT FRIEND WHO COME WIT CODE, SAY IT GOOD CODE. I CHECK, HE RIGHT! IS HERE

DATA READLINEMONAD A = VALUE A
                     | GETLINE (STRING -> READLINEMONAD A)

INSTANCE MONAD READLINEMONAD WHERE
  RETURN = VALUE
  VALUE X >>= F = F X
  GETLINE G >>= F = GETLINE $ \S -> G S >>= F

HA CLEVER!!! NOW WE NEED NO TYPE CONSTRAINTS BECAUSE NOW COMPUTATION IS MONAD ITSELF! HOW YOU ASK.

READLINEMONAD HAS NO IO OR ANY ELSE BUILTIN; IT GETS LINE BY CREATE FUNCTION WHICH TAKES LINE TO CONTINUU EXECUTION. AGAIN AND AGAIN! LINE CAN COME FROM ANYTHIN.

EXAMPLE FOR USING RESULT!

GETLINESFROMIO :: READLINEMONAD A -> IO A
GETLINESFROMIO (VALUE X) = RETURN X
GETLINESFROMIO (GETLINE F) = DO
  S <- GETLINE
  GETLINESFROMIO $ F S

U SEE WAT GOIN ON DERE! IN OUR LEXER WE NAMELI USED

GETLINE VALUE

TO GET LINE (BECAUSE FITS WITH CLEVER MONAD!)

NICE-O!

CODE IN QUSTION

LOOKIE HER FOR FULL DETAILS (ALTHOU WITH NO FULL CAPS): HTTPS://RARRW.GITHUB.COM/HIPERFIT/L0LANGUAGE/MASTER/SRC/LANGUAGE/L0/PARSER/PARSER.Y

CONCLUSION

THIS IS ENTRELY OBJECTIVE.

THIS IS ENTIREY OBJECTIVE.

THIS IS ENTIRLY OBJECTIVE.