Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Dwayne Crooks
Dwayne Crooks

Posted on

     

Using the Writer monad to refactor my interpreter

I recently started back working throughEoPL and yesterday Isolved exercise 3.15.

Extend the language by adding a new operationprint that takes one argument, prints it, and returns the integer 1. Why is this operation not expressible in our specification framework?

Since I'm using Haskell to complete these exercises this one presented a unique challenge becauseprint is not a pure function.

To solve it I decided to change the type of my interpreter from

valueOfProgram::Program->Value
Enter fullscreen modeExit fullscreen mode

to

valueOfProgram::Program->(Value,String)
Enter fullscreen modeExit fullscreen mode

but this had significant consequences on the readability of my code.

run::String->(Value,String)run=valueOfProgram.parsevalueOfProgram::Program->(Value,String)valueOfProgram(Programexpr)=valueOfExprexprinitEnvwhereinitEnv=Env.extend"i"(NumberVal1)(Env.extend"v"(NumberVal5)(Env.extend"x"(NumberVal10)Env.empty))valueOfExpr::Expr->Environment->(Value,String)valueOfExprexprenv=caseexprofConstn->(NumberValn,"")Varv->(Env.applyenvv,"")Diffab->let(aVal,s)=valueOfExpraenv(bVal,t)=valueOfExprbenvin(NumberVal(toNumberaVal-toNumberbVal),s++t)Zeroe->let(val,s)=valueOfExpreenvin(BoolVal(toNumberval==0),s)Iftestconsequentalternative->let(testVal,s)=valueOfExprtestenvinif(toBooltestVal)thenlet(result,t)=valueOfExprconsequentenvin(result,s++t)elselet(result,t)=valueOfExpralternativeenvin(result,s++t)Letvarebody->let(val,s)=valueOfExpreenv(result,t)=valueOfExprbody(Env.extendvarvalenv)in(result,s++t)Printe->let(val,s)=valueOfExpreenvin(NumberVal1,s++showval++"\n")
Enter fullscreen modeExit fullscreen mode

See the full changehere.

You see all the drudgery involved to ensure that the output string gets handled correctly.

I was able to use the Writer monad to hide all that drudgery and improve the readability of my code.

Look at it now.

run::String->(Value,String)run=runWriter.valueOfProgram.parsevalueOfProgram::Program->WriterStringValuevalueOfProgram(Programexpr)=valueOfExprexprinitEnvwhereinitEnv=Env.extend"i"(NumberVal1)(Env.extend"v"(NumberVal5)(Env.extend"x"(NumberVal10)Env.empty))valueOfExpr::Expr->Environment->WriterStringValuevalueOfExprexprenv=caseexprofConstn->return$NumberValnVarv->return$Env.applyenvvDiffab->doaVal<-valueOfExpraenvbVal<-valueOfExprbenvreturn$NumberVal(toNumberaVal-toNumberbVal)Zeroe->doval<-valueOfExpreenvreturn$BoolVal(toNumberval==0)Iftestconsequentalternative->dotestVal<-valueOfExprtestenvif(toBooltestVal)thenvalueOfExprconsequentenvelsevalueOfExpralternativeenvLetvarebody->doval<-valueOfExpreenvvalueOfExprbody(Env.extendvarvalenv)Printe->doval<-valueOfExpreenvtell$showval++"\n"return$NumberVal1
Enter fullscreen modeExit fullscreen mode

See the full changehere.

Takeaways

  1. Write the most obvious Haskell code that solves the problem. Don't worry about what's the best way to do it in Haskell at this point.

  2. Writetests to ensure the code works as expected.

  3. Refactor the code. At this point you have well tested working code but you think you can do better. Now is the best time to learn what techniques or ideas can help you improve the code. Read widely and expand your knowledge of Haskell.

P.S.This was not a post about how to use the Writer monad. It was a post about how the Writer monad helped me to write clearer Haskell code. To learn about the Writer monad I'd recommend the book "Haskell Programming from First Principles".

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Learn to build reliable web applications with Elm.
  • Location
    Trinidad & Tobago
  • Joined

More fromDwayne Crooks

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp