2011-06-22 55 views
9

Làm cách nào để sử dụng functors tiêu hóa để tạo biểu mẫu có danh sách hộp kiểm được tạo lập trình, sẽ trả về danh sách. Ví dụ:Danh sách hộp kiểm với tiêu hóa-functors

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

sẽ trả lại ["Milk", "Ground meat"].

tôi hy vọng loại sẽ là một cái gì đó như:

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

Trả lời

14

Không có cách nào tiêu chuẩn để làm như vậy, nhưng digestive-functors rất composable sử dụng giao diện Applicative, vì vậy bạn có thể dễ dàng tạo ra những gì bạn muốn.

Bạn có thể xác định checkBox trả về Maybe String, tức là tên của phần tử nếu nó được chọn.

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 

Bạn có thể sau đó lặp trên một danh sách các chuỗi để tạo ra một hộp kiểm như thế này cho mỗi phần tử trong danh sách:

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

Các catMaybes :: [Maybe a] -> [a] giúp bạn giảm kết quả hơn nữa:

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

Và cuối cùng, chúng tôi có thể khởi tạo biểu mẫu thực tế:

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

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

Thats khéo léo. Cảm ơn bạn – Masse

+0

'listForm'' có thể được viết đơn giản hơn bằng cách sử dụng' Data.Traversable' như 'listForm '= traverse'. – hammar

Các vấn đề liên quan