在Elm中,是否可以迭代联合类型?

15

我有一个颜色类型的联合体,我想将其呈现给用户。是否可以迭代所有类型联合值?

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) ]
4个回答

16

声明函数的问题如下:

type Foo 
  = Bar 
  | Baz

enumFoo = 
  [ Bar 
  , Baz ]

问题在于你可能会忘记将新的枚举类型添加到其中。为了解决这个问题,我一直在尝试这种(有些繁琐,但比上面的想法更好的)方法:

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

这样至少会在函数中得到一个错误,希望您不要忘记将其添加到列表中。


3
这实际上是针对这种限制的一个聪明的解决方法。谢谢! - pietro909
thing 是在哪里定义的? - JustGage
2
"ignored"是一个函数,所以"thing"是参数。该函数从未被调用,但它告诉编译器验证所有枚举是否在case语句中列出。它与下面的数组"[Bar,Baz]"完全分开--这种方法只是一种让编译器错误出现在列表附近,并提醒程序员添加一个条目到数组中的方式。 - Greg Edwards

9
很抱歉,不行。这是不可能的。
对于像你的“Color”类型这样只有有限值的简单类型,似乎编译器应该能够生成这样的列表。但就编译器而言,你的类型和像...一样的类型没有区别。
type Thing = Thing String

要迭代所有类型为 Thing 的值,需要迭代所有类型为 String 的值。

谢谢,不过我会使用一个简单的字符串列表。 - ondrej

3

当然可以做到。只是不能通过编译器自动完成。

type Foo 
   = Bar 
   | Baz
   | Wiz

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

这个代码可以正常工作,但如果编译器支持枚举,那么它会更好并且更全面地检查。
colorList = 
ul
    []
    List.map colorListItem enumFoo

1
这并不完全回答你的问题,但由于Elm与Haskell非常相似,我可能不是唯一想知道Haskell方面情况的人。因此,在Haskell中(展示ghci),您可以
Prelude> data Color = Red | Blue | Green | Black deriving (Show, Bounded, Enum)
Prelude> [minBound..maxBound]::[Color]
[Red,Blue,Green,Black]

也许elm的未来版本会借鉴这个。

编辑:我发现Haskell中获取所有可能数据类型值的列表,这也回答了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接