Hello everyone! First post here, but I lurked for a long time with another account
I have a problem with a design system built in Elm. I’m implementing a component with the builder pattern that render into an h2
tag by default. This tag could be changed by the user with an utility
withTag : String -> Config -> Config
withTag : nodeName (Config configuration) =
Config {configuration | tag = string}
The render part then use it this value from the configuration to build Html.node
.
I’ve two problems at hand right now which I was not be able to solve:
- Is there a way to restrict which Strings can be passed to
withTag
to a specif subset of allowed tags (e.g.h1
,h2
,h3
,h4
and so on)? - This behaviour will be replicated in another component but with a different list of allowed tags
I tried to define another opaque type Tag
with variants H1
, H2
etc. etc., to solve the first problem and then change withTag
to:
withTag : Tag -> Config -> Config
withTag : tag (Config configuration) =
Config {configuration | tag = tag}
and this works just fine. However I have now a problem with the second point since this union type cannot be restricted or expanded for others component that needs to have a different allowed set of tags.
I tried to look up at phantom types
as well with an implementation like
type Tag state = Tag String
type AllowedTag = AllowedTag
type DisallowedTag = DisallowedTag
tag : String -> Tag state
tag nodeName =
if nodeName == "h1" then
allowTag nodeName
else
disallowTag nodeName
allowTag : String -> Tag AllowedTag
allowTag =
Tag
disallowTag : String -> Tag DisallowedTag
disallowTag =
Tag
withTag : Tag Allowed -> Config msg -> Config msg
But sadly the method tag
won’t compile since the if branches return different types.
Is there a solution to this problem?