[Haskell-cafe] Problem with monadic formlets

Jeremy Shaw jeremy at n-heptane.com
Thu Aug 27 16:37:14 EDT 2009


Hello,

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.)

I get:

<label
>Username</label
><input type="text" name="input0" id="input0" value="name"
 /><label
>Password</label
><input type="password" name="input1" id="input1" value="password"
 /><label
>Password (confirm)</label
><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.

- jeremy

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
> http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list