如何避免榆树中自定义类型和字符串之间的往返?

How to avoid round trips between custom type and string in elm?

我遇到了自定义类型和 string 之间有很多往返的问题。当用户 clicks/changes 一个 textareadroplist in HTML 时,onInput 捕获一个 string 代表更新的值在该元素中。

然后消息会将此字符串发送到 update 函数以更新模型。 update 函数需要将 string 转换为 my custom type ,因为它是以这种方式建模的。

   type color = green | yellow | red

   type alias Model =
    { name :String
     ,skinColor: color}

   // to present `color` in html, it needs to be converted to string
   viewFruitColor c = 
   div [] [
       case c of 
          green -> "green"
          yellow ->  "yellow"
          red -> "red"
       ,onSelect ChangeColor
       ]
       // some ChangeColor msg here


  // in update function, which handles changing the color of fruit, it has to convert a string back to a type
   update msg model = 
       case msg of
          ChangeColor s    // s -> String here
              let newColor =  // can we just get `s` as a color type instead of a String ??
                     case s of 
                       "green"-> green
                       "yellow" -> yellow 
                       "red" -> red 
              in 
              { fruit | skinColor = newColor }

这仅适用于 model 中的一个字段,如果有多个字段,那会增加大量冗余代码,只是在 type 和 [=11= 之间往返](很多 case 个子句)

只是使用函数,elm 被设计成这样编写代码:

colorToString : color -> String
colorToString c =
       case c of 
          green -> "green"
          yellow ->  "yellow"
          red -> "red"

parseColor : String -> color
parseColor s =
        case s of 
           "green"-> green
           "yellow" -> yellow 
           "red" -> red
           _ -> red  -- it is a good idea to have a default, or otherwise use the Maybe type

然后你的代码就可以工作了,例如

viewFruitColor c = 
   div [] [
       colorToString c
       ,onSelect ChangeColor
       ] 

没有办法绕过它。用户可以向您发送任意字符串,您需要处理它。另一方面,在应用程序方面,最好像您一样使用代数类型,因为它可以更精确地定义域。总体策略是:

  • 您收到来自用户的字符串
  • 你用parseColor
  • 把它变成颜色
  • 你用 color
  • 做你的逻辑
  • 你用 colorToString
  • 把颜色变成字符串
  • 你把html发回去