[Haskell-cafe] Avoiding ad-hoc with yesod-form

MarLinn monkleyon at gmail.com
Mon Jul 24 12:54:38 UTC 2017

On 2017-07-24 12:54, Yotam Ohad wrote:
> […]
> Is there a better way to do it? 

Yes. AForm is Applicative. So you should just be able to use other 
applicative combinators.

For example (untested):

	fooAForm :: Int -> AForm Handler [Foo]
	fooAForm count = traverse makeFooField [1..count]

	    makeFooField :: Int -> AForm Handler Foo
	    makeFooField n = areq (selectFieldList foos) (makeFooName n) Nothing

	    foos :: [(Text, Role)]
	    foos = first tshow . join (,) <$> [minBound..]

Note that traverse works on any Traversable (Duh.), and the usual maps 
are all Traversable, so you can easily adapt this to return, say, a 
(Map String Foo) or a (Map FooName Foo). And similar methods work for 
monadic forms.

But: The way you asked the question smells like there might be something 
bad in either the user interface or the structural design. Maybe you 
want just one form with six fields plus CSS to conditionally hide some 
of them? Maybe you want one form with n fields plus an additional field 
to select the n? (Monadic fields should be able to do that.) Maybe 
there's no real maximum limit so you need just one field generator but a 
more complex front-end? I'm not saying you're doing it wrong, it's just 
that my nose is itching.


> This is how I defined the forms:
> foo2AForm :: AForm Handler Foo2
> foo2AForm = Foo2
>      <$> areq (selectFieldList foos) "foo1" Nothing
>      <*> areq (selectFieldList foos) "foo2" Nothing
>    where
>      foos:: [(Text, Role)]
>      foos= map (pack . show &&& id) [minBound..]
> […]

More information about the Haskell-Cafe mailing list