2011-06-22 15 views
9

¿Cómo utilizo los funtores digestivos para crear un formulario que tiene una lista de casillas de verificación generadas por programa, que devolvería una lista. Por ejemplo:Lista de casillas de verificación con funcionadores digestivos

[x] Milk 
[ ] Cereals 
[x] Ground meat 

devolvería ["Milk", "Ground meat"].

Estoy esperando el tipo sería algo así como:

form :: (Functor m, Monad m) => [String] -> HappstackForm m Html BlazeFormHtml [String] 

Respuesta

14

No hay forma estándar de hacerlo, pero es altamente digestive-functors componibles utilizando la interfaz Applicative, por lo que puede crear fácilmente lo que quiere.

Puede definir checkBox que devuelve Maybe String, es decir, el nombre del elemento si se marcó.

checkBox :: (Functor m, Monad m) 
     => String -> HappstackForm m Html BlazeFormHtml (Maybe String) 
checkBox str = fmap maybeStr (inputCheckBox False) <++ label str 
    where 
    maybeStr True = Just str 
    maybeStr False = Nothing 

A continuación, puede iterar sobre una lista de cadenas para crear una casilla de verificación como ésta para cada elemento de la lista:

listForm' :: (Functor m, Monad m) 
      => [String] 
      -> HappstackForm m Html BlazeFormHtml [Maybe String] 
listForm' = foldr (\x xs -> fmap (:) x <*> xs) (pure []) . map checkBox 

El catMaybes :: [Maybe a] -> [a] le ayuda a reducir el resultado adicional:

listForm :: (Functor m, Monad m) 
     => [String] 
     -> HappstackForm m Html BlazeFormHtml [String] 
listForm = fmap catMaybes . listForm' 

Y, por último, podemos crear una instancia de la forma real:

food :: [String] 
food = ["Milk", "Cereals", "Ground meat"] 

foodForm :: (Functor m, Monad m) 
     => HappstackForm m Html BlazeFormHtml [String] 
foodForm = listForm food 
+0

Eso es genial. Gracias – Masse

+0

'listForm'' se puede escribir de forma más simple utilizando' Data.Traventable' como 'listForm '= travesera checkBox'. – hammar

Cuestiones relacionadas