
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