<html><body><div style="color:#000; background-color:#fff; font-family:arial, helvetica, sans-serif;font-size:10pt">Hi folks,<br><br>As a follow-on question from my prior post, I got stuck on not being able to compile the following<br>code in my survey data model which basically generally unwraps the the inner type from the <br>wrapper:<br><br>extract :: Question' -&gt; Question a<br>
extract q = case q of<br>
&nbsp;&nbsp;&nbsp; QuestionS x -&gt; extractQString q<br>
&nbsp;&nbsp;&nbsp; QuestionI x -&gt; extractQInt q<br>
&nbsp;&nbsp;&nbsp; QuestionD x -&gt; extractQDouble q<br>
<br>and I had to produce the following instead:<br><br>extractQString :: Question' -&gt; Question String<br>
extractQString (QuestionS q) = q<br>
<br>
extractQInt :: Question' -&gt; Question Int<br>
extractQInt (QuestionI q) = q<br>
<br>
extractQDouble :: Question' -&gt; Question Double<br>
extractQDouble (QuestionD q) = q<br><br>An exchange in stackoverflow seems to suggest that the only way to do it is to use GADTs (which is a language extension).<br>http://stackoverflow.com/questions/6047522/haskell-type-and-pattern-matching-question-extracting-fields-from-a-data-type<br><br>I'm disinclined to use language extensions because I'd rather use haskell98 proper to begin with. So Is this indeed the case?<br>&nbsp;My code has become more verbose as a result and I am trying to learn most elegant and general haskell 'way' (if it exists) <br>and hence I would appreciate any advice to this end.<br><br>regards,<br><br>Alia<br>
<br><br>&lt;survey.hs&gt;<br><br>module Main where<br><br>import Text.Show.Functions<br>import Data.Maybe<br><br>type Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = String<br>type QuestionText&nbsp;&nbsp;&nbsp; = String<br>type Answer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = String<br>type Score&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Double<br>type CorrectAnswer a = a<br>type Option a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = (String, a)<br><br>-- type converters<br>str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = id<br>int s&nbsp;&nbsp;&nbsp; = read s :: Int<br>double s = read s :: Double<br><br>data QuestionType&nbsp;&nbsp; = Open<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Test <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Choice
 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deriving (Show, Eq)<br><br>data Question a = Question<br>&nbsp;&nbsp;&nbsp; { questionName&nbsp;&nbsp;&nbsp; :: Name<br>&nbsp;&nbsp;&nbsp; , questionText&nbsp;&nbsp;&nbsp; :: QuestionText<br>&nbsp;&nbsp;&nbsp; , questionType&nbsp;&nbsp;&nbsp; :: QuestionType<br>&nbsp;&nbsp;&nbsp; , answerFunc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :: (String -&gt; a)<br>&nbsp;&nbsp;&nbsp; , correctAnswer&nbsp;&nbsp; :: Maybe a<br>&nbsp;&nbsp;&nbsp; , options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :: Maybe [Option a]<br>&nbsp;&nbsp;&nbsp; } deriving (Show)<br><br>data Question' = QuestionS (Question String) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | QuestionI (Question Int) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | QuestionD (Question
 Double)&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deriving (Show)<br><br>data QuestionSet = QuestionSet<br>&nbsp;&nbsp;&nbsp; { qsetTitle&nbsp;&nbsp;&nbsp;&nbsp; :: String<br>&nbsp;&nbsp;&nbsp; , qsetQuestions :: [Question']<br>&nbsp;&nbsp;&nbsp; , qsetPoints&nbsp;&nbsp;&nbsp; :: Double<br>&nbsp;&nbsp;&nbsp; } deriving (Show)<br><br>data Survey = Survey<br>&nbsp;&nbsp;&nbsp; { surveyTitle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :: String<br>&nbsp;&nbsp;&nbsp; , surveyQuestionSets :: [QuestionSet]<br>&nbsp;&nbsp;&nbsp; } deriving (Show)<br><br><br><br>parse :: Question a -&gt; Answer -&gt; a<br>parse = answerFunc<br><br>view&nbsp; :: Question a -&gt; String<br>view q = questionName q<br><br>ask&nbsp;&nbsp; :: Question a -&gt; IO ()<br>ask q = putStrLn $ questionText q<br><br>store :: Question a -&gt; Answer -&gt; IO ()<br>store q ans = putStrLn $ questionName q ++ ": " ++ show
 ans<br><br>{-<br>extract :: Question' -&gt; Question a<br>extract q = case q of<br>&nbsp;&nbsp;&nbsp; QuestionS x -&gt; extractQString q<br>&nbsp;&nbsp;&nbsp; QuestionI x -&gt; extractQInt q<br>&nbsp;&nbsp;&nbsp; QuestionD x -&gt; extractQDouble q<br>-}<br><br>extractQString :: Question' -&gt; Question String<br>extractQString (QuestionS q) = q<br><br>extractQInt :: Question' -&gt; Question Int<br>extractQInt (QuestionI q) = q<br><br>extractQDouble :: Question' -&gt; Question Double<br>extractQDouble (QuestionD q) = q<br><br>testQ :: (Eq a) =&gt; Question a -&gt; Answer -&gt; Bool<br>testQ q ans = case (correctAnswer q) of<br>&nbsp;&nbsp;&nbsp; Nothing -&gt; False<br>&nbsp;&nbsp;&nbsp; Just x&nbsp; -&gt; x == (answerFunc q $ ans)<br><br>testQ' :: Question' -&gt; Answer -&gt; Bool<br>testQ' q a = case q of<br>&nbsp;&nbsp;&nbsp; QuestionS x -&gt; testQS q a<br>&nbsp;&nbsp;&nbsp; QuestionI x -&gt; testQI q a<br>&nbsp;&nbsp;&nbsp; QuestionD x -&gt; testQD q
 a<br>&nbsp;&nbsp;&nbsp; where<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testQS q a = testQ (extractQString q) a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testQI q a = testQ (extractQInt&nbsp;&nbsp;&nbsp; q) a<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testQD q a = testQ (extractQDouble q) a<br><br><br>testQset :: QuestionSet -&gt; [Answer] -&gt; [Bool]<br>testQset qs as = zipWith testQ' (qsetQuestions qs) as<br><br><br>evalQset :: QuestionSet -&gt; [Answer] -&gt; Score<br>evalQset qs as = (total_correct / total_questions) * score<br>&nbsp;&nbsp;&nbsp; where<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_questions = fromIntegral (length $ qsetQuestions qset)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total_correct = fromIntegral (length $ filter (== True) (testQset qset as))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; score = qsetPoints qset<br><br><br>q1 = Question<br>&nbsp;&nbsp;&nbsp; { questionName&nbsp; =
 "q1"<br>&nbsp;&nbsp;&nbsp; , questionText&nbsp; = "What is our name?"<br>&nbsp;&nbsp;&nbsp; , questionType&nbsp; = Open<br>&nbsp;&nbsp;&nbsp; , answerFunc&nbsp;&nbsp;&nbsp; = id<br>&nbsp;&nbsp;&nbsp; , correctAnswer = Nothing<br>&nbsp;&nbsp;&nbsp; , options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Nothing<br>&nbsp;&nbsp;&nbsp; }<br><br>q2 = Question<br>&nbsp;&nbsp;&nbsp; { questionName&nbsp; = "q2"<br>&nbsp;&nbsp;&nbsp; , questionText&nbsp; = "What is 1+1?"<br>&nbsp;&nbsp;&nbsp; , questionType&nbsp; = Test<br>&nbsp;&nbsp;&nbsp; , answerFunc&nbsp;&nbsp;&nbsp; = int<br>&nbsp;&nbsp;&nbsp; , correctAnswer = Just 2<br>&nbsp;&nbsp;&nbsp; , options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Nothing<br>&nbsp;&nbsp;&nbsp; }<br><br>q3 = Question<br>&nbsp;&nbsp;&nbsp; { questionName&nbsp; = "q3"<br>&nbsp;&nbsp;&nbsp; , questionText&nbsp; = "What is 2+1?"<br>&nbsp;&nbsp;&nbsp; , questionType&nbsp; = Choice<br>&nbsp;&nbsp;&nbsp; , answerFunc&nbsp;&nbsp;&nbsp; =
 int<br>&nbsp;&nbsp;&nbsp; , correctAnswer = Just 3<br>&nbsp;&nbsp;&nbsp; , options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Just [("a", 2), ("b", 3), ("c", 4)]<br>&nbsp;&nbsp;&nbsp; }<br><br>q4 = Question<br>&nbsp;&nbsp;&nbsp; { questionName&nbsp; = "q4"<br>&nbsp;&nbsp;&nbsp; , questionText&nbsp; = "What is 2.0 + 1.5 ?"<br>&nbsp;&nbsp;&nbsp; , questionType&nbsp; = Choice<br>&nbsp;&nbsp;&nbsp; , answerFunc&nbsp;&nbsp;&nbsp; = double<br>&nbsp;&nbsp;&nbsp; , correctAnswer = Just 3.5<br>&nbsp;&nbsp;&nbsp; , options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Just [("a", 2.1), ("b", 3.5), ("c", 4.4)]<br>&nbsp;&nbsp;&nbsp; }<br><br><br>qset = QuestionSet<br>&nbsp;&nbsp;&nbsp; { qsetTitle&nbsp;&nbsp;&nbsp;&nbsp; = "simple questions"<br>&nbsp;&nbsp;&nbsp; , qsetQuestions = [ QuestionS q1 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , QuestionI q2
 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , QuestionI q3<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; , QuestionD q4<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]<br>&nbsp;&nbsp;&nbsp; , qsetPoints&nbsp;&nbsp;&nbsp; = 100.0<br>&nbsp;&nbsp;&nbsp; }<br><br>survey = Survey<br>&nbsp;&nbsp;&nbsp; { surveyTitle&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = "a survey"<br>&nbsp;&nbsp;&nbsp; , surveyQuestionSets = [qset]<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>t1 = evalQset qset ["1", "2", "3", "4"]<br><br>&lt;/survey.hs&gt;<br><br><br></div></body></html>