jaspervdj / digestive-functors

A general way to consume input using applicative functors
149 stars 71 forks source link

Is the Formlet type signature for the listOf function necessary? #123

Closed cimmanon closed 8 years ago

cimmanon commented 9 years ago

I'm writing an application for surveys that allows a dynamic list of questions, but I want to allow the possible answers to be unique for each question.

When I pull my list of questions out of the database, they are of this type:

data Question = Question
    { question :: Text
    , answers :: [Text]
    } deriving (Show, Eq)

When the form is submitted, I only need to know the provided answer for each question, so my ideal form would look something like this:

questionForm' :: Monad m => Maybe Question -> Form Text m (Text, Text)
questionForm' q = ( , )
    <$> "question" .: text (question <$> q)
    <*> "answer" .: choiceWith choices Nothing
    where
        toChoice x = (x, (x, x))
        choices = maybe [] (map toChoice . answers) q

Due to the Formlet (Maybe a -> Form v m a) requirement for listOf, this is not allowed. I created a copy of the function with a less restrictive type signature that allows for Maybe a -> Form v m b forms, and it appears to work:

listOf' :: (Monad m, Monoid v)
       => (Maybe a -> Form v m b)
       -> (Maybe [a] -> Form v m [b])
listOf' single def =
    List (fmap single defList) (indicesRef .: listIndices ixs)
  where
    ixs = case def of
        Nothing -> [0]
        Just xs -> [0 .. length xs - 1]

    defList = DefaultList Nothing $ maybe [] (map Just) def

Is there a good reason to keep the current, more restrictive type signature that I'm not aware of?

jaspervdj commented 8 years ago

This is a great point, I'll switch it to the less restrictive version.