I am trying to have associated "data items" of ContentType of and its content:
data ContentType = MyInt | MyBool deriving ( Show )
data Encoding'
= EncodingInt [Int]
| EncodingBool [Bool]
chooseContentType :: IO ContentType
chooseContentType = undefined
How do I make something like this, but type-checked?
data Encoding a =
Encoding { contentType :: ContentType
, content :: [a]
}
The feature you're looking for is called generalized algebraic data types (or GADTs, for short). It's a GHC extension, so you'll have to put a pragma at the top of your file to use them. (I'm also including
StandaloneDeriving, because we'll use that to get yourShowinstance in a minute)Now you can define your
ContentTypetype fully. The idea is thatContentTypeis parameterized by the (eventual) type of its argument, soContentTypewill have kind* -> *(i.e. it will take a type argument).Now we're going to write it with a bit of a funny syntax.
This says that
MyIntisn't just aContentType; it's aContentType Int. We're keeping the type information alive inContentTypeitself.Now
Encodingcan be written basically the way you have it.Encodingalso takes a type parametera. Its content must be a list ofa, and its content type must be a content type that supports the typea. Since our example has only defined two content types, that means it must beMyIntfor integers orMyBoolfor Booleans, and no other encoding will be supported.We can recover your
deriving (Show)onContentTypewith aStandaloneDerivingclause (this is the second GHC extension we turned on in the above pragma)This is equivalent to your
derivingclause, except that it sits on its own line since the GADT syntax doesn't really have a good place to put one in the same line.