【问题标题】:elm - executing multiple lines in a functionelm - 在一个函数中执行多行
【发布时间】:2016-05-08 15:33:53
【问题描述】:

在 elm 中,是否可能类似于以下内容

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

上面的目的是执行多行代码?

如果不是,是不是因为上面是副作用的例子?

如果无法实现上述语法,如何同时执行两个函数/两行代码,如上所述,或者作为给定输入(案例分支)的结果?

编辑

以上是一个不好的例子。以下使用 Elm 架构:

--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 
    ]

鉴于此,我是否正确假设以更改基础模型的方式“执行多行”,只需使用/扩展模型 - 例如,实现类似于以下的更改:

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

只需将模型扩展如下:

--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

【问题讨论】:

  • 如果您关注The Elm Architecture,则所有状态更改或副作用都应该发生在update 函数中。如果您实现了不同的东西,那么我们希望看到更多详细信息。
  • @halfzebra 感谢上述 - 可以在update case 语句中执行多个语句吗?
  • 简而言之,不,但是您可以通过稍微不同的方式实现所需的行为。您是否尝试过在update 中使用Let Expressions?您对 Elm 架构的熟悉程度如何?
  • @halfzebra 我在update 语句中经常使用let 表达式进行解构,但这如何实现多语句执行?
  • 这取决于addToNumHistory 到底应该做什么,例如,您可以在update 内部let 表达式内部使用不同的操作再次运行update。这会有帮助吗?

标签: functional-programming elm side-effects


【解决方案1】:

在这种特定情况下,您不需要有副作用。

我不得不添加两个实用函数来创建一个正常运行的示例。

  • onInput 处理'input' 事件
  • parseIntString 检索 Int

其余的是 0.16 的基本 Elm 架构生命周期

请考虑我为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
    }

【讨论】:

  • 感谢广度,包括正确处理输入。关于我编辑的后半部分 - 模型扩展通常可以很好地替代多行语句执行吗?
  • @category 乐于助人!如果你说的是addToNumHistory 的实现,那很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多