Shawn Zhang
Shawn Zhang

Reputation: 1884

How to view custom type in elm?

here is data model , the goal is easy, just to view the type Gift in the HTML and user can use a dropdown list to update field type_ of Gift. But the question is how to build dropdown list from a custom type ?

type Fruit
    = Apple
    | Banana
    | Orange

type alias Gift = 
{ quantity : int
  type_ : Fruit
}

I tried to add a update/view operation on view

how to convert the type Fruit to String ? There are two possible workarounds:

  1. Building a dict, which mays Fruit to String

     {Apple:"Apple",Banana,"Banana"}
    

    I don't think this will work since key in Dict needs to be Comparable,but how to implement ordering in custom type ? there was an issue but there seems no solution yet (https://github.com/elm/compiler/issues/774)

  2. Using Enum/makeEnum module this will bring more code and easily can break.

     fruitTypeEnum = Enum.makeEnum [Apple, Banana, Orange ]
    
     -- in view
     (List.map (\x -> Enum.toString fruitTypeEnum x) [Apple,Banana,Orange])
    

    this has to maintain apple,banana,orange list in three places ( including the declaration )

Thank you for your time reading this .Appreciate any help:)

Upvotes: 2

Views: 319

Answers (3)

PerLundholm
PerLundholm

Reputation: 96

To answer the other question about using other types as keys in Dict, there is the possibility to use assoc-list instead: https://package.elm-lang.org/packages/pzp1997/assoc-list/latest/

import AssocList as Dict exposing (Dict)


type Fruit
    = Apple
    | Banana
    | Orange


fruitStrings : Dict Fruit String
fruitStrings =
    Dict.fromList
        [ ( Apple, "Apple" )
        , ( Banana, "Banana" )
        , ( Orange, "Orange" )
        ]


fruitToString : Fruit -> String
fruitToString fruit =
    Dict.get fruit fruitStrings |> Maybe.withDefault "Not a fruit"

As you can see, with a Dict you need to handle a case that could never happen. The case construction is therefore preferable here. But now you know how to create a dictionary with custom types as keys.

Upvotes: 0

bdukes
bdukes

Reputation: 156055

There is no built in way in Elm to get a list of all of the variants of a custom type (Elm generally shies away from "magic" metaprogramming in favor of explicitness). As glennsl answered, using a case expression is a very clean and straightforward way to implement a toString function for a custom type.

The list of all variants of that type must be keep separately from the type definition itself, but you should create one list, maybe named allFruit in this case, that you can use anywhere you want to list them all out. Tests can help you ensure you don't miss anything when asking a new variant.

One more advanced technique is using code generation to create a list from the source code automatically.

Upvotes: 4

glennsl
glennsl

Reputation: 29146

I'll only answer the first question here (see my comment). No Dict needed, it's a simple function:

fruitToString : Fruit -> String
fruitToString fruit =
  case fruit of
    Apple -> "Apple"
    Banana -> "Banana"
    Orange -> "Orange"

Upvotes: 3

Related Questions