Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping data constructors to types

I'm creating an application that allows an admin to build a form, which a user can fill out. Questions can be of different types. Each kind of question corresponds to a type of response data.

Is it possible to encode this at the type level? How would you organize this?

data QuestionType = EmailText | PlainText | Numeric

-- this doesn't have any response information, it's the metadata
-- about the question itself.
data Question = { id :: ID, label :: Text, questionType :: QuestionType }

data Answer = { questionID :: ID, response :: Response }

-- I would like to map those question types to different response types
data Response = ???
-- EmailText => Text
-- PlainText => Text
-- Numeric   => Int

I've thought about Type Families, which would work perfectly except that I want to map from different data constructors to different types, and type families would require separate types for each one.

This would be a good fit for a single ADT, with the response information included in each constructor, but I need to be able to deal with question types independently from responses.

How should I approach this?

like image 500
Sean Clark Hess Avatar asked Jan 07 '23 07:01

Sean Clark Hess


1 Answers

I've not completely understood what you exactly want, but maybe this can be a starting point:

{-# LANGUAGE DataKinds, GADTs #-}

data Response (qt :: QuestionType) where
  RPlainText :: Text -> Response PlainText
  REmailText :: Text -> Response EmailText
  RNumeric :: Int -> Response Numeric

data Answer qt = Answer {questionID :: ID, response :: Response qt}

If you do not want the qt argument in Answer qt, you probably need existential types to hide that, but at that point you'll probably want to link it with the questions somehow.

like image 84
chi Avatar answered Jan 15 '23 11:01

chi