如何使用消化函子创建一个表单,该表单具有以编程方式生成的复选框列表,该列表将返回一个列表。例如:
[x] Milk
[ ] Cereals
[x] Ground meat
会回来["Milk", "Ground meat"]
的。
我期待的类型会是这样的:
form :: (Functor m, Monad m) => [String] -> HappstackForm m Html BlazeFormHtml [String]
如何使用消化函子创建一个表单,该表单具有以编程方式生成的复选框列表,该列表将返回一个列表。例如:
[x] Milk
[ ] Cereals
[x] Ground meat
会回来["Milk", "Ground meat"]
的。
我期待的类型会是这样的:
form :: (Functor m, Monad m) => [String] -> HappstackForm m Html BlazeFormHtml [String]
没有标准的方法可以做到这一点,但digestive-functors
使用该界面可高度组合Applicative
,因此您可以轻松创建所需的内容。
您可以定义 a checkBox
,它返回 a Maybe String
,即元素的名称(如果它被选中)。
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
然后,您可以遍历字符串列表,为列表中的每个元素创建一个像这样的复选框:
listForm' :: (Functor m, Monad m)
=> [String]
-> HappstackForm m Html BlazeFormHtml [Maybe String]
listForm' = foldr (\x xs -> fmap (:) x <*> xs) (pure []) . map checkBox
catMaybes :: [Maybe a] -> [a]
可以帮助您进一步减少结果:
listForm :: (Functor m, Monad m)
=> [String]
-> HappstackForm m Html BlazeFormHtml [String]
listForm = fmap catMaybes . listForm'
最后,我们可以实例化实际的表单:
food :: [String]
food = ["Milk", "Cereals", "Ground meat"]
foodForm :: (Functor m, Monad m)
=> HappstackForm m Html BlazeFormHtml [String]
foodForm = listForm food