2016-06-30 15 views
9

Ich habe eine Art Union von Farben, die ich dem Benutzer rendern möchte. Ist es möglich, über alle Typ-Vereinigungswerte zu iterieren?Ist es möglich, über Union-Typ in Elm zu iterieren?

type Color = Red | Blue | Green | Black 

colorToStirng color = 
    case color of 
     Red -> "red" 
     Blue -> "blue" 
     Green -> "green" 
     Black -> "black" 

colorList = 
    ul 
     [] 
     List.map colorListItem Color -- <- this is the missing puzzle 

colorListItem color = 
    li [class "color-" ++ (colorToString color) ] [ text (colorToString color) ] 

Antwort

6

Leider nein. Es ist nicht möglich.

Für einen einfachen Typ mit einer endlichen Anzahl von Werten wie Ihrem Typ könnte es scheinen, dass der Compiler in der Lage sein sollte, eine solche Liste zu erzeugen. Soweit die complier obwohl betroffen ist, gibt es keinen Unterschied zwischen Typ und einem Typ wie

type Thing = Thing String 

iterieren alle Werte vom Typ Thing dann alle erfordern würde Iterieren über die Werte des Typs String.

+0

danke trotzdem. Ich werde stattdessen eine einfache Liste von Strings verwenden. –

3

Oh natürlich können Sie es tun. Einfach nicht automatisch über den Compiler.

type Foo 
    = Bar 
    | Baz 
    | Wiz 

-- just write this for types 
-- you wish to use as enumerations 
enumFoo = 
    [ Bar 
    , Baz 
    , Wiz ] 

Das funktioniert ganz gut, aber wäre natürlich schöner und exhaustivity geprüft, ob Aufzählung jemals vom Compiler unterstützt wird.

colorList = 
ul 
    [] 
    List.map colorListItem enumFoo 
10

Das Problem mit einer Funktion wie erklärt:

type Foo 
    = Bar 
    | Baz 

enumFoo = 
    [ Bar 
    , Baz ] 

ist, dass Sie wahrscheinlich neue Aufzählungen, um es hinzuzufügen vergessen werden. Um dies zu lösen, ich habe mit diesem zu spielen (hacky, aber weniger hacky als die Idee oben) Idee:

enumFoo : List Foo 
enumFoo = 
    let 
    ignored thing = 
     case thing of 
      Bar -> () 
      Baz ->() 
      -- add new instances to the list below! 
in [ Bar, Baz ] 

So kann man zumindest einen Fehler für die Funktion und hoffentlich nicht vergessen, hinzuzufügen, es auf die Liste.

+3

Dies ist eigentlich eine intelligente Problemumgehung für eine solche Einschränkung. Vielen Dank! – pietro909

+0

Wo wird "Ding" definiert? – JustGage

+1

"ignoriert" ist eine Funktion, also "Sache" ist das Argument. Die Funktion wird nie aufgerufen, aber sie weist den Compiler an, zu überprüfen, ob alle Aufzählungen in der case-Anweisung aufgeführt sind. Es ist vollständig getrennt von dem Array darunter - "[Bar, Baz]" - dieser Ansatz ist nur eine Möglichkeit, einen Compiler-Fehler in der Nähe der Liste erscheinen zu lassen, mit einer Erinnerung für den Programmierer, einen Eintrag zum Array hinzuzufügen. –