I am a beginner at haskell, and I hit a wall during a toy project. I am simply trying to model a unit and a container which can units and containers as members. I want to serialize the unit and the container as xml maybe other formats afterwards. Here is what I have so far
module Model where
import Data.Map ( Map ) -- importing type
import Data.Text ( Text )
data ModelInfo = InfoCons {
modelId :: Text, modelType :: Text,
modelAttrs :: Map Text Text
} deriving (Show, Eq)
data UnitModel = UnitCons { unitInfo :: ModelInfo, unitData :: Text} deriving (Show, Eq)
data ContainerModel = ContainerCons { containerInfo :: ModelInfo
, containerData :: [ContainerData]} deriving (Show, Eq)
data ContainerData = NestedCons ContainerModel
| SimpleCons UnitModel
deriving (Show, Eq)
These are my models. They are mostly inspired from here. Here are my rendering functions:
class ModelRenderer model where
-- function definition
addIdType2Props :: (model -> ModelInfo) -> model -> Map Txt.Text Txt.Text
addIdType2Props f mdl = add2Map
(modelAttrs (f mdl))
[(Txt.pack "id", modelId (f mdl)),
(Txt.pack "type", modelType (f mdl))]
makeElement :: model -> Xml.Element
-- transform unit model to xml
instance ModelRenderer UnitModel where
makeElement um = Xml.Element
{ Xml.elementName = makeName (Txt.pack "unit")
, Xml.elementAttributes = convertTxt2NameMap
(addIdType2Props unitInfo um)
, Xml.elementNodes = [Xml.NodeContent (unitData um)]
}
-- transform container model to xml
instance ModelRenderer ContainerModel where
makeElement cm = Xml.Element
{ Xml.elementName = makeName (Txt.pack "container")
, Xml.elementAttributes = convertTxt2NameMap
(addIdType2Props containerInfo cm)
, Xml.elementNodes = map (Xml.NodeElement . makeElement)
(containerData cm)
}
The problem is I can't figure out how to render ContainerData
with my current knowledge on haskell. I want to typecheck the value that constructs the ContainerData
but I know that it is not the haskell way. Any suggestions ?
I think you can use pattern matching for that. Something like
instance ModelRenderer ContainerData where
makeElement (NestedCons cm) = makeElement cm
makeElement (SimpleCons um) = makeElement um
You can adapt this to the full ContainerModel
, adding the tags you wish.