Hi all,
imagine the following types:
type Node
= Node String (List Feature)
type Feature
= Main (List Node)
| Custom String (List Node)
| Text (List Node)
| None
I’m working on an API that allows users to build models with these types. However, I have, amongst others, the following requirement:
A node must not contain a Feature variant more than once. The exception is the Custom variant, where there can be 0…n, however, each Custom Feature must have a unique identifier (the first argument of type String of the Custom constructor).
To achieve that, I expose an API that let’s users add Nodes to the specific Feature.
-- exposed
underMain : Node -> Node -> Node
underMain (Node idParent features) child =
Node idParent (addToMainFeature child features)
-- local
addToMainFeature : Node -> List Feature -> List Feature
addToMainFeature child features =
let
(mainChildren, otherFeatures) =
-- collects all children already under the Feature in question (Main) and puts them together with the new ones
List.foldl
(\feature (mChildren, featuresOther) ->
case feature of
Main children ->
(mChildren ++ children, featuresOther)
_ ->
(mChildren, feature :: featuresOther)
)
([child], [])
features
in
Main mainChildren :: otherFeatures
My implementation idea is to use foldl to collect all children that already exist under a certain Feature (e.g. the Main feature) prepend a new Main feature with all these children at the end. Neither the order of Features nor of Nodes matters at that point.
My specific questions are:
- Is there a easier / better way to satisfy my requirement
- I’d have to copy the
addToXXXFeaturefunction for theTextfeature, and only changecase ofinside the anonymous function to match against theTextconstructor. Can this be unified somehow? I’m thinking of aaddToFeature : Feature -> Node -> List Feature -> List Featurefunction where the first parameter is theFeatureto put the new node under. However, I don’t understand how I could pattern match the passedFeaturevariant to the onefoldlis processing…?