...through composing the standard library functions using the Monad's Typeclass methods.
codegen and metaprogramming - recall
...through implementing Template Haskell functions for NCurry and NCompose.
frontend design - recall
...through implementing a Parsec Parser for a prefix arithmetic language.
Note: For recall learning objectives, please tell me what skill you had to apply again and where it was originally applied.
Note: There are more opportunities for gaining Recognition learning objectives in this assignment if you apply these techniques onto similar problems that have the same pattern that I point out or that you find yourself.
TL;DW: The components of the language design pipeline for desinging DSLs in this class will be implemented using some common monads in Haskell. IO for app and library code, Q for metaprogramming, and ParsecT (Parser) for lexing and parsing concrete syntax. The assignment that follows are small exercises that touch on each of these. And in a later assignment, we will be putting these pieces together.
Some notes about the template project:
TL;DW:
IO modules can be run with stack exec io1 and stack exec io2
Tests can be run individually with stack test using-monads:{test suite name}
-ddump-splices ghc argument was added to stack.yaml
The IO Monad
Note: Feel free to start the rest of the homework first, and if you are confused, then
look at these slides and/or this video. It is long, but detailed. I suggest looking through the
slides first until you find the slide relevant to what you want to know, and then
find the corresponding part in the lecture video.
Lecture slides
TL;DW
Haskell relies on being lazy and using memoization to do some cool compiler optimizations
These properties and optimizations don't play nice with side effects e.g. IO
Monads give us a design pattern for describing computation compositionally while preserving sequence
Do-notation lets us fake an imperative concrete syntax for side effecting code
Homework Description
TL;DW
Implement an IO program that reads a file, sorts the lines alphabetically, and then writes the result to a {filename}.results file.
Run with stack exec io1 file.
Implement an IO program that randomly picks a number, prompts the user for a number, says whether they are too high or too low, and terminates when they guess correctly.
Run with stack exec io2 file .
Template Haskell - Q Monad
TL;DW
Implement a TH program (computation in the Q Monad) for NCurry - a compile time function that when given an integer n, produces a higher order function that given an argument f :: (t1,...,tn) -> t and n curried inputs, evaluates f on a tuple of all the inputs.
Make sure tests in test/ncurry/Main.hs pass with stack test using-monads:ncurry-tests.
Debug using the files found by running find . -name "*dump-splices".
Implement a TH program (computation in the Q Monad) for NCompose - a compile time function that when given an integer n, produces a higher order function that given arguments g and f produces a function that takes n arguments, applies them to f, and then applies g to the result.
Make sure tests in test/ncompose/Main.hs pass with stack test using-monads:ncompose-tests.
Parser (ParsecT)
TL;DW
You are going to be using parser combinators from Parsec to build up a monadic computation.
This monadic computation will consume a string as input (behind the scenes) and produce an Arithmetic expression represented as an algebraic data type.
The concrete syntax of this string will be a lisp-y style prefix notation for +,-,*,/, and integers.
make sure all the tests in test/arith/Main.hs pass with stack test using-monads:arith-tests.
(Optional) Recognition Points
Technically, any part of any homework is optional if you already have the learning objective
for that part. But alas...
Should you want to do more or achieve deeper learning objectives, I highly encourage it.
Consider the list of small word problems below for which I believe a IO, TH, or Parser Monadic implementation could help. Sketch a solution and a short description of what design pattern or skill from this homework you Recognized in the problem for advanced points.
I am defining a datatype to represent a high-level language. I am writing compiler passes that slowly desugar this language into a simpler one. E.g. I am going to turn all of the Let* expressions into nested Lets, and then all of the Let expressions into Lambdas.
I don't want to write 3 copies of my Exp data type with one data constructor removed each time, nor the function to convert between them. What can I do?
I want to test if my network ports are already bound to applications listening on them. Can I write a functional program to do that?
I have an Algebraic Data Type representing JSON files. I need to understand them from my functional programs in order to talk to internet services. How can I read them from a string?
I miss default arguments from other programming languages. I.e. f x=5 = x + 3 where now I can call f 10 and get 13 or f and get 8. Is there a way I can get close to this behavior in Haskell. What about the concrete syntax?
META.md
META.md should include
Your name.
Your utln.
How much time you spent on this assignment.
The witness "proof" for how you earned each learning objective with a note about recall for recall objectives and what problem you recognized in the recognization objectives.
Please Submit
Contents to be submitted
Your copy of hw06-1-using-monads.
META.md
Method of submission
Please commit your changes in the hw06-1-using directory of your private repo and push them to the remote server before 9 am.