Shawn Zhang
Shawn Zhang

Reputation: 1884

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

I encountered an issue that there are lots of round trip between a custom type and string . When user clicks/changes an textarea or droplist in HTML, the onInput caputures a string that represents the updated value in that element.

Then the message would send this string to update function to update the model. The update function need to convert that string to my custom type , since it was modeled that way.

   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 }

this is only for one single field in model, what if there are mutilple fields, that would boost up a lots of reduntant codes just taking round trips between type and string (lots of case clauses)

Upvotes: 2

Views: 107

Answers (1)

radrow
radrow

Reputation: 7159

Just use functions, elm was designed to write code like this:

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

And then your code would work for example like

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

There is no way to bypass it. The user can send you an arbitrary string and you need to handle it. On the other hand, on the app side it is good to work with algebraic types as you do, because it defines the domain more precisely. The overall strategy is:

  • you receive a string from a user
  • you turn it to color with parseColor
  • you do your logic with color
  • you turn the color to string with colorToString
  • you send the html back

Upvotes: 4

Related Questions