Skip to content

Instantly share code, notes, and snippets.

@dela3499
Created August 15, 2015 04:09
Show Gist options
  • Save dela3499/ca95842fd12a640ed7be to your computer and use it in GitHub Desktop.
Save dela3499/ca95842fd12a640ed7be to your computer and use it in GitHub Desktop.
import StartApp.Simple exposing (start)
import Html exposing (..)
import Html.Events exposing (onClick, on, targetValue)
import String
{--
Modified from: https://gist.github.com/bbugh/bf150a8be595068de88c
As I undestand it, the spec for this calculator is:
- If I input a valid integer and click an operator like Multiply,
update the accumulator and show the result.
- If my input can't be turned into an integer,
don't change the accumulator, but show an error message.
-------------------------------------------------------------
Here's one attempt to make this work in a clear, DRY way.
I've changed the model, so that it contains:
- inputString: the raw user input as a string
- accumulator: this is an integer as before
- output: this is a string that gets shown to the user. It's either
the string version of the calculation result, or an error message.
When the user updates the input, this triggers the UpdateInputString action.
The update function replaces model.inputString with the string provided
by the action. At this point, there's no attempt to convert the string
into an integer.
The interesting part comes when the user triggers the Multiply action
(or Divide, or any other operator). This executes handleOperatorAction,
which takes a model and a two-argument function like (*), which is the
prefix version of the multiply function.
Once inside handleOperatorAction, the inputString is finally converted to a
Result Int. If the inputString can be successfully converted to an integer,
then the accumulator is updated with the result of the appropriate computation,
and the output is updated with the string version of this result. If the
conversion is not possible, then the accumulator is left unchanged, and
the output message is the error message from Err.
Lastly, the view function has been updated. I've removed the extra div for the
error message, since both the error message and valid result are both shown
by model.output. Also, since model.output is a string, rather than and integer,
it doesn't need to be converted at this stage.
--}
type alias Model =
{
inputString: String,
accumulator: Int,
output: String
}
initialModel : Model
initialModel =
{
inputString = "0",
accumulator = 3,
output = "3"
}
type Action
= Multiply
| Divide
| UpdateInputString String
update: Action -> Model -> Model
update action model =
case action of
Multiply ->
handleOperatorAction model (*)
Divide ->
handleOperatorAction model (//)
UpdateInputString str ->
{ model | inputString <- str}
handleOperatorAction: Model -> (Int -> Int -> Int) -> Model
handleOperatorAction model operatorFunction =
case (String.toInt model.inputString) of
Ok value ->
let result = operatorFunction model.accumulator value
in { model
| accumulator <- result
, output <- toString result }
Err msg ->
{ model | output <- msg }
onTextInput : Signal.Address a -> (String -> a) -> Attribute
onTextInput address f =
on "input" targetValue (\v -> Signal.message address (f v))
view : Signal.Address Action -> Model -> Html
view address model =
div [] [
input [ onTextInput address UpdateInputString ] [ ],
button [ onClick address Multiply ] [ text "*" ],
text model.output
]
main : Signal Html.Html
main =
start { model = initialModel, update = update, view = view }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment