Creating a form with Elm
Question: I would like to create a form in Elm that takes 4 required inputs:

  * 3 floating point values
  * 1 input which can take the values of "long" or "short" (presumably) this would be a drop-down

When the values are entered, a computation occurs that yields a single line of
output based on these values.

I have this working as a command-line Python program:

    
    
    #!/usr/bin/env python
    
    
    from __future__ import print_function
    
    # core
    import logging
    
    # pypi
    import argh
    
    # local
    
    logging.basicConfig(
        format='%(lineno)s %(message)s',
        level=logging.WARN
    )
    
    def main(direction, entry, swing, atr):
    
        entry = float(entry)
        swing = float(swing)
        atr   = float(atr)
    
        if direction == 'long':
            sl = swing - atr
            tp = entry + (2 * atr)
        elif direction == 'short':
            sl = swing + atr
            tp = entry - (2 * atr)
    
        print("For {0} on an entry of {1}, SL={2} and TP={3}".format(
            direction, entry, sl, tp))
    
    if __name__ == '__main__':
        argh.dispatch_command(main)
    

but want to use Elm to create a web UI for it.


Answer: This isn't an ideal first introduction to Elm, since it takes you through a
few of Elm's more difficult areas: mailboxes and the Graphics.Input library.
There is also not an easy-to-deploy number input, so I've only implemented the
dropdown; you'd use [Graphics.Input.Field](http://package.elm-
lang.org/packages/elm-lang/core/2.1.0/Graphics-Input-Field) (which can get
particularly dicey).

A mailbox is basically a signal that the dropdown input can send a message to.
I've chosen for that message to be a function, specifically, how to produce a
new state from the old one. We define state to be a record type (like a Python
named tuple), so saving the direction involves storing the new direction in
the record.

The text is rendered using a convenience function that makes it `monospace`.
There's a whole [text library](http://package.elm-lang.org/packages/elm-
lang/core/2.1.0/Text) you can use, but Elm 0.15 does not have string
interpolation, so you're stuck with the quite ugly appends.

Finally, there's not much on an Elm community on SO, but you're welcome to
join the [mailing list](https://groups.google.com/forum/#!forum/elm-discuss)
where questions like this are welcomed. That being said, you really should try
to dive into Elm and learn the basics so you can ask a more specific question.
This is true of almost any language, library or framework - you have to do
some basic exercises before you can write "useful" code.

    
    
    import Graphics.Input as Input
    import Graphics.Element as Element exposing (Element)
    
    mailbox = Signal.mailbox identity
    
    type Direction = Short | Long
    type alias State = {entry : Float, swing : Float, atr : Float, dir : Direction}
    
    initialState : State
    initialState = State 0 0 0 Short
    
    dropdown : Element
    dropdown =
        Input.dropDown
        (\dir -> Signal.message mailbox.address (\state -> {state| dir <- dir}))
        [("Short", Short), ("Long", Long)]
    
    state : Signal State
    state = Signal.foldp (<|) initialState mailbox.signal
    
    render : State -> Element
    render state =
        dropdown `Element.above`
        Element.show ("For "++(toString state.dir)++" on an entry of "++(toString state.entry) ++
                      ", SL="++(toString (sl state))++" and TP="++(toString (tp state)))
    
    main = Signal.map render state
    
    -- the good news: these are separate, pure functions
    sl {entry, swing, atr, dir} =
        case dir of
            Long -> swing - atr
            Short -> swing + atr
    
    tp {entry, swing, atr, dir} =
        case dir of
            Long -> entry + (2*atr)
            Short -> entry - (2*atr)
    

Update: I wrote [an essay](https://gist.github.com/mgold/461dbf37d4d34767e5da)
on mailboxes and how to use them.

