1

In elm, is something like the below possible

foo : Int -> Html
foo inputNum =
  addToNumHistory inputNum ;
  display inputNum

where the aim of the above is to execute multiple lines of code?

If not, is this because the above is an example of a side effect?

If something like the above syntax is not possible, how would one go about executing two functions/lines of code simultaneously, as in the above, or as a result of a given input (case branch) ?

Edit

The above is a bad example. The following uses the Elm Architecture:

--Model
type alias Model =
  { number : Int
  , numberHistory : List Int
  }

type Action
  = Number Int


--Update
update : Action -> Model
update action =
  case action of
    Number num->
      addToNumHistory num           

addToNumHistory : Int -> Model -> Model 
addToNumHistory num modelHistory =
  { model 
    | number = num
    , numberHistory = num :: model.numberHistory
  }

--View     
view : Signal.Address Action -> Model -> Html
view action model =
  div []
    [  field 
       "text" 
       address 
       Number model.number
       "Enter lucky number here pal!"
       model.number 
    ]

Given this, am I right in presuming that to 'execute multiple lines' in such a fashion as to alter an underlying model, one would simply use/extend the model - for example, to effect a change analogous to the following:

--Update
update : Action -> Model
update action =
  case action of
    Number num->
      addToNumHistory num;
      addToChangeHistory

one would simply extend the model as follows:

--Model
type alias Model =
  { number : Int
  , numberHistory : List Int
  , changeHistory : List Date
  }

--Update
update : Action -> Model
update action =
  case action of
    Number num->
      addToNumHistoryWithChangeHistory num

addToNumHistoryWithChangeHistory : Int -> Model -> Model 
addToNumHistory num modelHistory =
  { model 
    | number = num
    , numberHistory = num :: model.numberHistory
    , changeHistory = getCurrentDate :: model.changeHistory
  }

getCurrentDate : Date
category
  • 2,113
  • 2
  • 22
  • 46
  • 1
    If you're following the [The Elm Architecture](https://github.com/evancz/elm-architecture-tutorial), all state changes or side-effects are supposed to happen in the `update` function. If you have implemented something different, then we would like to see more details. – halfzebra May 08 '16 at 16:32
  • @halfzebra Thanks for the above - can execution of multiple statements then happen in the `update` case statement? – category May 08 '16 at 18:34
  • In short no, but _you can achieve the desired behavior_ in a slightly different way. Have you tried using [Let Expressions](http://elm-lang.org/docs/syntax#let-expressions) inside of `update`? How familiar are you with Elm Architecture? – halfzebra May 08 '16 at 20:26
  • @halfzebra I use `let` expressions in `update` statements quite frequently for destructuring, but how would this achieve multiple statement execution? – category May 08 '16 at 20:33
  • It depends on what exactly `addToNumHistory` is supposed to do, for example you can run `update` again with a different action inside of `update` inside of `let` expression. Would that help? – halfzebra May 08 '16 at 20:46
  • Could you show the type of `addToNumHistory`? – Søren Debois May 09 '16 at 07:07
  • @halfzebra I think you're original comment hit the nail on the head, edited question to that effect. – category May 09 '16 at 09:29
  • @Søren Debois - edited question with said type and the above. – category May 09 '16 at 09:29

1 Answers1

2

In this specific case, you don't need to have side-effects.

I've had to add two utility functions to create a functioning example.

  • onInput to handle 'input' event
  • parseInt to retrieve Int from a String

The rest is a basic Elm Architecture lifecycle as of 0.16

Please consider this minimal example I made for use with StartApp.Simple:

import Html exposing (text, input, div, Html, Attribute)
import Html.Attributes exposing (value)
import Html.Events exposing (on, targetValue)
import String
import Signal exposing (Address)
import StartApp.Simple as StarApp


--Utils
onInput : Address a -> (String -> a) -> Attribute
onInput address f =
  on "input" targetValue (\v -> Signal.message address (f v))


parseInt : String -> Int
parseInt string =
  case String.toInt string of
    Ok value ->
      value

    Err error ->
      0


--Model
type alias Model =
  { number : Int
  , numberHistory : List Int
  }


initModel : Model
initModel =
  { number = 0
  , numberHistory = []
  }


--Update


type Action
  = UpdateNumber String


update : Action -> Model -> Model
update action model =
  case action of
    UpdateNumber num -> 
       addToNumHistory (parseInt num) model


addToNumHistory : Int -> Model -> Model 
addToNumHistory num model =
  { model 
    | number = num
    , numberHistory = num :: model.numberHistory
  }


--View     
view : Signal.Address Action -> Model -> Html
view address model =
  div
    []
    [ input
        {- On every 'input' event,
           grab the value of input field and send to UpdateNumber
        -}
        [ onInput address UpdateNumber, value (toString model.number) ]
        []
    , div [] [ text (toString model.number) ]
    , div
        []
        ( model.numberHistory
          |> List.reverse
          |> List.map (toString)
          |> List.map text
        )
    ]


main : Signal Html
main =
  StarApp.start
    { view = view
    , update = update
    , model = initModel
    }
halfzebra
  • 6,771
  • 4
  • 32
  • 47
  • Thanks for the breadth, including handling input properly. Regarding the latter part of my edit - is model extension in general a good substitution for multi-line statement execution? – category May 09 '16 at 14:11
  • @category happy to help! If you're talking about your implementation of `addToNumHistory`, it's perfectly fine. – halfzebra May 09 '16 at 15:47