简体   繁体   中英

purescript data as array of all possible data inhabitants

I got the following data type:

data Icon = IconCircle | IconSquare | IconStar

I need an array of all possible Icon s?:

allPossible :: Array Icon
allPossible = [IconCircle, IconSquare, IconStar]

Is there a shortcut to create this array? eg when there are 20 (or a lot more) possible Icons?

When not:

Is it possible to create a type for allPossible that forces all possible Icons to be included?

My goal is to force that this array is never incomplete.

Yes, there is!

You can derive Generic and then use GenericEnum in combination with GenericBottom to enumerate all constructors:

data Icon = IconCircle | IconSquare | IconStar
derive instance Generic Icon _

allPossible :: Array Icon
allPossible = unfoldr (\a -> Tuple a <$> genericSucc a) genericBottom

And you can even make this completely generic, so it would work for any type, not just for Icon :

allPossible :: forall a rep. 
  Generic a rep =>
  GenericEnum rep => 
  GenericBottom rep => 
  Array a
allPossible = unfoldr (\a -> Tuple a <$> genericSucc a) genericBottom

Of course, this will only work for types that are actually enums - ie every constructor is either parameterless or its parameters have instances of Enum . If the type is not an enum in this sense, this will fail to compile, complaining that it's impossible to construct a GenericEnum instance.

Fyodor's answer is incorrect unfortunately. The last value is omitted because it is mapped on it's non existing successor (ie Nothing).

A working alternative might be:

allPossible :: Array Icon
allPossible = unfoldr (\b -> b >>= next) $ Just genericBottom
  where
    next a = Just $ Tuple a $ genericSucc a

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM