<commit_before>ghcjs-setup
===========

```bash
git clone --recursive <EMAIL>:ryantrinkle/try-reflex
cd try-reflex
./try-reflex
```

This will install the Nix package manager, grab the ghcjs package information, build everything, then give you access to a sandbox with ghcjs and node.js available.  The first time you run it, the build process will take a long time - up to several hours.  After that, it should only take a few moments.

You will need sudo access in order to install Nix (unless you are on NixOS).  However, you should run the script as yourself, not root - it will prompt for your password when necessary.<commit_msg>update readme to include tutorial<commit_after>Try Reflex
==========
Setup
-----
The steps below will set up an environment from which you can use GHCJS and Reflex. This process will install the [Nix package manager](https://nixos.org/nix/). If you prefer to install it yourself, you may do so any time prior to step 2.

1. Clone the try-reflex repo:

    ```bash
        git clone --recursive <EMAIL>:ryantrinkle/try-reflex
    ```

2. Navigate into the `try-reflex` folder and run the try-reflex bootstrapping command. This will install nix, if you don't have it already, and use it to wrangle all the dependencies you'll need and drop you in an environment from which you can use Reflex. Be warned, this might take a little while the first time:

    ```bash
        ./try-reflex
    ```
If you hit an error about unfree licenses, you need to add `{ allowUnfree = true; }` to your `~/.nixpkgs/config.nix`. You may need to create the `~/.nixpkgs` folder and add the `config.nix` file.

3. From this nix-shell, you can compile your haskell source using ghcjs:

    ```bash
        ghcjs --make source.hs
    ```
    This should look fairly familiar to anyone who has compiled with ghc.

4. Compilation will produce a `source.jsexe` folder containing an `index.html` file. Open that in your browser to run your app.

Code
----
In this example, we'll be following [Luite Stegemann's lead](http://weblog.luite.com/wordpress/?p=127) and building a [simple functional reactive calculator](./main.jsexe/index.html) to be used in a web browser.

### DOM Basics

Reflex's companion library, Reflex.Dom contains a number of functions used to build and interact with the DOM. Let's start by getting a basic app up and running.

```haskell
    import Reflex.Dom

    main = mainWidget $ el "div" $ text "Welcome to Reflex"
```

Saving this line and compiling it produces a `source.jsexe` folder, where `source` is the same as the filename of the source file you compiled. Inside the `source.jsexe` folder you'll find `index.html`. Opening that in your browser will reveal a webpage with a single div containing the text "Welcome to Reflex".

Most Reflex apps will start the same way: a call to `mainWidget` with a starting `Widget`. A `Widget` is some DOM wrapped up for easy use with Reflex. In our example, we are building the argument to `mainWidget`, (in other words, our starting `Widget`) on the same line.

`el` has the type signature:

```haskell
    MonadWidget t m => String -> m a -> m a
```

The first argument to `el` is a `String`, which will become the tag of the html element produced. The second argument is a `Widget`, which will become the child of the element being produced.

In our example, `el "div" $ text "Welcome to Reflex"`, the first argument to `el` was `"div"`, indicating that we are going to produce a div element.

The second argument to `el` was `text "Welcome to Reflex"`. The type signature of `text` is:

```haskell
    MonadWidget t m => String -> m ()
```

`text` takes a `String` and produces a `Widget`. The `String` becomes the `innerHTML` of the parent element of the `text`. Of course, instead of a `String`, we could have used `el` here as well to continue building arbitrarily complex DOM. For instance, if we wanted to make a unordered list:

```haskell
    import Reflex.Dom

    main = mainWidget $ el "div" $ do
      el "p" $ text "Reflex is:"
      el "ul" $ do
        el "li" $ text "Fast"
        el "li" $ text "Memory Safe"
        el "li" $ text "Higher Order"
        el "li" $ text "Glitch-free"
```

### Dynamics and Events
Of course, we want to do more than just view a static webpage. Let's start by getting some user input and printing it.

```haskell
    import Reflex.Dom

    main = mainWidget $ el "div" $ do
      t <- textInput
      dynText $ _textInput_value t
```

Running this in your browser, you'll see that it produces a `div` containing an `input` element. When you type into the `input` element, the text you enter appears inside the div as well.

`textInput` is a function with the following type:

```haskell
    textInput :: MonadWidget t m => m (TextInput t)
```

It takes no arguments, and produces a `Widget` containing a `TextInput`. In `Reflex.Dom.Widget.Input` we can see that a `TextInput` exposes the following functionality:

```haskell
    data TextInput t
      = TextInput { _textInput_value :: Dynamic t String
                  , _textInput_keypress :: Event t Int
                  , _textInput_keydown :: Event t Int
                  , _textInput_keyup :: Event t Int
                  , _textInput_hasFocus :: Dynamic t Bool
                  , _textInput_element :: HTMLInputElement
                  }
```

Here we are using `_textInput_value` to access the `Dynamic String` value of the `TextInput`. Conveniently, `dynText` takes a `Dynamic String` and displays it. It is the dynamic version of `text`.

We can also access `Event`s related to the `TextInput`. For example, consider the following code:

```haskell
    import Reflex
    import Reflex.Dom

    main = mainWidget $ el "div" $ do
      t <- textInput
      text "Last key pressed: "
      let keypressEvent = fmap show $ _textInput_keypress t
      keypressDyn <- holdDyn "None" keypressEvent
      dynText keypressDyn
```

Here, we are creating a `TextInput` as we were before. The function `_textInput_keypress` gives us an `Event Int` representing the key code of the pressed key. We are using `fmap` here to apply `show` to the `Int`, so the type of `keypressEvent` is `Event String`. Whenever a key is pressed inside the `TextInput`, the `keypressEvent` will fire.
`holdDyn` allows us to take create a `Dynamic` out of an `Event`. We must provide an initial value for the `Dynamic`. This will be the value of the `Dynamic` until the associated `Event` fires. The type of `holdDyn` is:

```haskell
    MonadHold t m => a -> Event t a -> m (Dynamic t a)
```

We won't go into the details of `MonadHold` here, but the rest of the type signature should be fairly clear: `holdDyn` takes an initial value, an `Event` containing a value of the same type as the initial, and returns a `Dynamic` containing a value of the same type.

When you run this application, you'll see a textbox and the string "Last key pressed: None" on the screen. Recall that "None" is the initial value we gave `holdDyn`.

### A Number Input
A calculator was promised, I know. We'll start building the calculator by creating an input for numbers.

```haskell
    import Reflex
    import Reflex.Dom
    import qualified Data.Map as Map

    main = mainWidget $ el "div" $ do
      t <- input' "number" "0" never (constDyn Map.empty)
      dynText $ _textInput_value t
```

The `textInput` function we used earlier is implemented in terms of `input'`. The type signature of `input'` is:

    input' :: MonadWidget t m => String -> String -> Event t String -> Dynamic t (Map String String) -> m (TextInput t)

The first argument is a `String` that specifies the html input element's `type` attribute. We're using `"number"` here.

The second argument is the initial value of the `TextInput`. We gave it `"0"`. Even though we're making an html `input` element with the attribute `type=number`, the result is still a `String`. We'll convert this later.

The third argument is an `Event String`. This is an `Event` that sets the value of the `TextInput` when it fires. We supplied `never` for this argument. `never` represents an event that will never fire.

The final argument is a `Dynamic (Map String String)` representing the html element attributes other than `type`. It is `Dynamic`, allowing the input's attributes to change dynamically. This can be used to, for instance, apply error styling depending on the value of the `TextInput`. We are passing an empty `Map` here, since we don't need to set any of the html attributes other than `type`. The function `constDyn` takes a pure value and turns it into a `Dynamic` that never changes value.

Let's do more than just take the input value and print it out. First, let's make sure the input is actually a number:

```haskell
    import Reflex
    import Reflex.Dom
    import qualified Data.Map as Map
    import Safe (readMay)

    main = mainWidget $ el "div" $ do
      t <- numberInput
      numberString <- mapDyn show t
      dynText numberString

    numberInput :: MonadWidget t m => m (Dynamic t (Maybe Double))
    numberInput = do
      n <- input' "number" "0" never $ constDyn Map.empty
      mapDyn readMay $ _textInput_value n
```

We've defined a function `numberInput` that handles both the creation of the `TextInput` and reads its value. Recall that `_textInput_value` gives us a `Dynamic String`. The final line of code in `numberInput` uses `mapDyn` to apply the function `readMay` to the `Dynamic` value of the `TextInput`. This produces a `Dynamic (Maybe Double)`. Our `main` function uses `mapDyn` to map over the `Dynamic (Maybe Double)` produced by `numberInput` and `show` the value it contains. We store the new `Dynamic String` in `numberString` and feed that into `dynText` to actually display the `String`

Running the app at this point should produce an input and some text showing the `Maybe Double`. Typing in a number should produce output like `Just 12.0` and typing in other text should produce the output `Nothing`.

### Adding
Now that we have `numberInput` we can put together a couple inputs to make a basic calculator.

```haskell
    import Reflex
    import Reflex.Dom
    import qualified Data.Map as Map
    import Safe (readMay)
    import Control.Applicative ((<*>), (<$>))

    main = mainWidget $ el "div" $ do
      nx <- numberInput
      text " + "
      ny <- numberInput
      text " = "
      result <- combineDyn (\x y -> (+) <$> x <*> y) nx ny
      resultString <- mapDyn show result
      dynText resultString

    numberInput :: MonadWidget t m => m (Dynamic t (Maybe Double))
    numberInput = do
      n <- input' "number" "0" never $ constDyn Map.empty
      mapDyn readMay $ _textInput_value n
```

`numberInput` hasn't changed here. Our `main` function now creates two inputs. `combineDyn` is used to produce the actual sum of the values of the inputs. The type signature of `combineDyn` is:

    (Reflex t, MonadHold t m) => (a -> b -> c) -> Dynamic t a -> Dynamic t b -> m (Dynamic t c)

You can see that it takes a function that combines two pure values and produces some other pure value, and two `Dynamic`s, and produces a `Dynamic`.

In our case, `combineDyn` is combining the results of our two `numberInput`s (with a little help from `Control.Applicative`) into a sum.

We use `mapDyn` again to apply show to `result` (a `Dynamic (Maybe Double)`) resulting in a `Dynamic String`. This `resultString` is then displaying using `dynText`.

### Supporting Multiple Operations
Next, we'll add support other operations. We're going to add a dropdown so that the user can select the operation to apply. The function `dropdown` has the type:

```haskell
    dropdown :: (MonadWidget t m, Ord k, Show k, Read k) => k -> Dynamic t (Map k String) -> m (Dropdown t k)
```

The first argument is the initial value of the `Dropdown`. The second argument is a `Dynamic (Map k String)` that represents the options in the dropdown. The `String` values of the `Map` are the strings that will be displayed to the user. If the initial key is not in the `Map`, it is added and given a `String` value of `""`.

Our supported operations will be:

```haskell
    ops = Map.fromList [("+", "+"), ("-", "-"), ("*", "*"), ("/", "/")]
```

We'll use this as an argument to `dropdown`:

```haskell
    d <- dropdown "*" $ constDyn ops
```

We are using `constDyn` again here to turn our `Map` of operations into a `Dynamic`. The result, `d`, will be a `Dropdown`. We can retrieve the `Dynamic` selection of a `Dropdown` by using `_dropdown_value`.

```haskell
    import Reflex
    import Reflex.Dom
    import qualified Data.Map as Map
    import Safe (readMay)
    import Control.Applicative ((<*>), (<$>))

    main = mainWidget $ el "div" $ do
      nx <- numberInput
      d <- dropdown "*" $ constDyn ops
      ny <- numberInput
      values <- combineDyn (,) nx ny
      result <- combineDyn (\o (x,y) -> stringToOp o <$> x <*> y) (_dropdown_value d) values
      resultString <- mapDyn show result
      text " = "
      dynText resultString

    numberInput :: (MonadWidget t m) => m (Dynamic t (Maybe Double))
    numberInput = do
      n <- input' "number" "0" never (constDyn Map.empty)
      mapDyn readMay $ _textInput_value n

    ops = Map.fromList [("+", "+"), ("-", "-"), ("*", "*"), ("/", "/")]

    stringToOp s = case s of
                        "-" -> (-)
                        "*" -> (*)
                        "/" -> (/)
                        _ -> (+)
```

This is our complete program. We've added an uninteresting function `stringToOp` that takes a `String` and returns an operation. The keys of the `Map` we used to create the `Dropdown` had the type `String`. When we retrieve the value of `Dropdown`, we'll use `stringToOp` to turn the `Dropdown` selection into the function we need to apply to our numbers.

After creating the two `numberInput`s, we combine them using `combineDyn` applying `(,)`, making a tuple of type `Dynamic (Maybe Double, Maybe Double)` and binding it to `values`.

Next, we call `combineDyn` again, combining the `_dropdown_value` and `values`. Now, instead of applying `(+)` to our `Double` values, we use `stringToOp` to select an operation based on the `Dynamic` value of our `Dropdown`.

Running the app at this point will give us our two number inputs with a dropdown of operations sandwiched between them. Multiplication should be pre-selected when the page loads.
{'fraction_non_alphanumeric': 0.09463590883824347, 'fraction_numerical': 0.0011117287381878821, 'mean_word_length': 3.350967351874244, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 45, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2689157', 'n_tokens_mistral': 4172, 'n_tokens_neox': 3966, 'n_words': 2069}