User Tools

Site Tools


cs330_f2016:elm1

This is an old revision of the document!


Objective:

The purpose of this lab is to help you understand how to use Functional Reactive Programming(FRP) in the Elm language to create a GUI. It is also to expand your idea of what a type can be by using Algebraic Data Types (ADTs).


Pre-requisite:

Make sure that you have the Elm compiler installed. Get it at https://guide.elm-lang.org/install/elm.html.


Auxiliary files needed:

  • index.css
  • index.html
  • Lab9.elm

Deliverable:

A single .elm file with your source code that successfully compiles to a JavaScript package that will run tic-tac-toe in the browser. In order to make tic-tac-toe, you will need to implement the following types:

  • Model
  • Msg

… and the following functions:

  • init :: Model
  • update :: Msg → Model → Model
  • and parts of view :: Model → Html Msg

Whenever writing Elm code (or any code, for that matter), it is a good idea to write many small functions with a specific purpose and then build more complicated functions from them. That said, you should feel free to make helper functions to break up the code needed for these required functions.


Description:

Web Programming/Compiling Elm

Elm is a “delightful language for reliable webapps”. As such, it was made with the intent for it to be used as a front-end development platform. We recognize that not everyone taking CS 330 will have experience making webapps, so we have provided for you all the boilerplate to make your code work in the browser.

You are provided with 3 files:

  • index.html, the entry-point for the app
  • index.css, the stylesheet to make everything look right.
  • Lab9.elm, the template Elm file that you fill in with your code.

If you open index.html in your browser it will open a totally white page. That is because in order for the webapp to run, index.html depends on a JavaScript file called tic-tac-toe.js. We will create this file by compiling our Elm to JS.

Before we can compile the Elm file into JS, we need to run the elm init function inside the directory where you put the files. This will create a file called “elm.json” which is necessary for compiling but you will not need to modify.

Now, to compile your Elm project so that it can be viewed in the browser, run the following command:

elm make Lab9.elm --output=tic-tac-toe.js

If you run that command with the code we provided unmodified, it will give you an error because there are unimplemented types and functions. Let's start implementing them.


Implementing the functions

One useful feature that Elm boasts is helpful and descriptive error messages. The creators' intent was for the compiler to act like a coding buddy. Using what the Elm developers call “Compiler Driven Development”, you can use the compiler error messages to help you get to working code. So do not be afraid to run the compile command to figure out what to fix next.

The first thing you will need to do is create an ADT called Model. Model will be a type for an object that represents the state of the program. Once you have defined the Model type, you will then need to implement the init function. init will return an instance of Model that will be the initial state of the program. In our case, the initial state of our program is a blank tic-tac-toe board and the player who's turn it is.

Next, create a type called Msg. When the user interacts with the webapp in some way (clicks a button, in our app) the runtime will be sent an instance of Msg. So, Msg should carry information about the interaction.

Once you have a definition for Msg and Model you can start implementing the update function. This function will will be called by the runtime whenever it receives a Msg which is whenever the user pushes a button. update will be passed the Msg instance and the current Model from the runtime and will return a new model. For example, the runtime may receive a message saying that the X-player clicked on the square at the top-left. The update function should then return a Model that reflects the appropriate change: the top-left corner is marked with an X and it is now the O-player's turn. Bear in mind that you are not performing any mutation of variables, only returning a new version of the Model.

You will then need to finish the implementation of the view function. This function's purpose is to take the current model from the runtime and produce a user interface of HTML elements based on that model. HTML elements are made in Elm by calling functions imported from the Html module that take as arguments a list of properties and a list of HTML elements. Notice that these elements of type Html Msg. This tells the runtime that these UI elements cary with them the capability of sending messages of type Msg back to the runtime.

Some of this function has already been implemented for you and you do not need to modify it further. There are two parts of it that have parentheses with a comment saying “Your code here”. In the first set of parentheses, write an expression that evaluates to a List of Html Msg instances that represent the the tic-tac-toe board. This should effectively produce a game board in the UI that reflects the model that was passed to the view function. I would suggest you make the parts of the board that are clickable (blank spots) into buttons. The code to make a button that sends the message SomeMsg with the text “I am a button” would look like this:

button [ onClick SomeMsg ] [ text "I am a button" ]

After a button has been selected it should be replaced with a div that has some text saying which player selected that tile. The code to make a div with some text inside is like this:

div [] [ text "I am a div" ]

The next thing to modify inside of view is the part that says “\*TODO\*: Place whose turn it is here”. In place of that string, put a string that says whose turn it is based on the passed-in model.

Then, after that there is a button with the text “Reset” and the onClick attribute is left blank. Fill that part in with some that evaluates to a Msg that should be sent to the runtime when the reset button is clicked.


The final product

When you're finished, your app should show a 3×3 grid of buttons, a piece of text that says whose turn it is, and a reset button. When a button on the grid is pushed it should be replaced with an X or O depending on whose turn it was when the button was pushed, and the text should change to show that it is now the next player's turn. When the reset button is pushed, the grid should go back to its start state and the turn should go back to the first player. NOTE: You do NOT have to check if a player has won the game.


Hints

  • You may want to represent the game board model as a one-dimensional list of “squares”. Squares could be their own type.
  • If you decide to use a one dimensional list, you may want to use Elm's List.indexedMap function.

Resources

cs330_f2016/elm1.1584984195.txt.gz · Last modified: 2021/06/30 23:40 (external edit)