[Haskell-cafe] Problem with monadic formlets
jeremy at n-heptane.com
Thu Aug 27 16:37:14 EDT 2009
I hacked your code into a runnable example, and it seems to work for me. What happens if you do something like:
let (c, xml, _) = runFormState [("input0",Left "name"), ("input1", Left "password"), ("input2", Left "password") ] "" (register "foo") in c >>= \r -> do print xml >> print r
(except you need to pass in a Database instead of "foo" as the argument to register.)
><input type="text" name="input0" id="input0" value="name"
><input type="password" name="input1" id="input1" value="password"
><input type="password" name="input2" id="input2" value="password"
Success (Registration "name" "password")
Which looks correct to me. Your code looks fine to me as
well... Perhaps the error is not in the code you pasted, but somewhere
else. I am running on an older, and somewhat forked version of
Formlets, so there could also be a bug in the new code I
guess. Though, that seems unlikely. But it is worth noting that we are
not using the same version of the formlets library.
At Thu, 27 Aug 2009 16:09:18 +0100,
Colin Paul Adams wrote:
> I'm trying to validate user input against a database (using HaskellDB,
> but that doesn't seem to be the problem, as replacing the database
> monadic code with return True gives the same problem.
> This is part of my code:
> register :: Database -> XForm Registration
> --register db = Registration <$> pure_user <*> passConfirmed
> register db = Registration <$> (user db) <*> passConfirmed
> user :: Database -> XForm String
> user db = pure_user `F.checkM` F.ensureM valid error where
> valid name = do
> let q = do
> t <- table user_table
> restrict (t!user_name .==. constant name)
> return t
> rs <- query db q
> return $ null rs
> error = "Username already exists in the database!"
> pure_user :: XForm String
> pure_user = input `F.check` F.ensure valid error where
> input = "Username" `label` F.input Nothing
> valid = (>= 3) . length
> error = "Username must be three characters or longer."
> passConfirmed :: XForm String
> passConfirmed = fst <$> passwords `F.check` F.ensure equal error where
> passwords = (,) <$> pass "Password" <*> pass "Password (confirm)"
> equal (a, b) = a == b
> error = "The entered passwords do not match!"
> pass :: String -> XForm String
> pass caption = input `F.check` F.ensure valid error where
> input = caption `label` F.password Nothing
> valid = (>=6) . length
> error = "Password must be six characters or longer."
> If I uncomment the commented line, and comment out the line after it
> (in register), then everything works as expected. However, using it as
> it is, one of the calls to pass gets the user's name for validation
> (and consequently either fails if the user name is only 5 characters,
> or the comparison of the two passwords fail (unless I type the user
> name as the password).
> I thought the applicative style meant the effects did not influence
> one another, but here there is clear contamination. What am i doing wrong?
> Colin Adams
> Preston Lancashire
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
More information about the Haskell-Cafe