Yesod's Applied Forms

I played a bit with Yesod, and the question arose: how are forms used as Applicatives?

Take:

    personForm :: Html -> MForm Synopsis Synopsis (FormResult Person, Widget)
personForm = renderDivs $ Person
    <$> areq textField "Name" Nothing
    <*> areq (jqueryDayField def
        { jdsChangeYear = True -- give a year dropdown
        , jdsYearRange = "1900:-5" -- 1900 till five years ago
        }) "Birthday" Nothing
    <*> aopt textField "Favorite color" Nothing
    <*> areq emailField "Email address" Nothing
    <*> aopt urlField "Website" Nothing

I do not understand how the operator <*>, which, as I understand it, takes as its first argument a type f (a -> b)(i.e. a functor containing a binary function) applied to the values AForm:

(AForm f) <*> (AForm g) = AForm $ \mr env ints -> do ...

What's going on here?

https://github.com/yesodweb/yesod/blob/bf293e6a1f6e691281520d254f72b9441cc64704/yesod-form/Yesod/Form/Types.hs#L95

+5
source share
1 answer

This helps here if you try to slightly ignore the detailed types and look at the big picture.

Think <$>and <*>as special versions $, which operate at a different level.

Applicative functors in general

- , AF,

x :: AF a
y :: AF b
z :: AF c

, " -", a, b c,

f :: a -> b -> c -> d

, d.

f <$> x <*> y <*> z    :: AF d

"do" x, y, z f .

, f $ a $ b $ c.

, f <$> x <*> y <*> z

do
  a <- x
  b <- y
  c <- z
  return (f a b c)

, ( ). areq aopt AForm sub master ??. sub master - / . ?? - .


areq textField "Name" Nothing - , Text,
areq (jqueryDayField def) "Birthday" Nothing - , a Day,
Text.

data Person = Person Text Day Text Text Text

Person :: Text -> Day -> Text -> Text -> Text -> Person, ,

Person
    <$> areq textField "Name" Nothing
    <*> areq (jqueryDayField def
        { jdsChangeYear = True -- give a year dropdown
        , jdsYearRange = "1900:-5" -- 1900 till five years ago
        }) "Birthday" Nothing
    <*> aopt textField "Favorite color" Nothing
    <*> areq emailField "Email address" Nothing
    <*> aopt urlField "Website" Nothing

, Person, Person.

,

do
    name    <- areq textField "Name" Nothing
    day     <- areq (jqueryDayField def
              { jdsChangeYear = True -- give a year dropdown
              , jdsYearRange = "1900:-5" -- 1900 till five years ago
              }) "Birthday" Nothing
    color   <- aopt textField "Favorite color" Nothing
    email   <- areq emailField "Email address" Nothing
    website <- aopt urlField "Website" Nothing

    return $ Person name day color email website

, , .

, <$> <*>?

, ,

pureFunction <$> af1 <*> af2 <*> af3 <*> af4 ....

<$> <*> . , , pureFunction . . ( .) :

<$> :: Functor f     =>    (a -> b) -> f a -> f b
<*> :: Applicative f =>  f (a -> b) -> f a -> f b

, <$> , <*>, , , <$> . , (++) "Hello", :: String -> String,

         getLine             :: IO String             -- produces a String
(++) <$> getLine             :: IO (String -> String) -- produces an appender
(++) <$> getLine <*> getLine ::            IO String  -- produces a combined String

areq textField "Name" Nothing
   :: AForm sub master Text

Person :: Text -> Day -> Text -> Text -> Text -> Person, name::Text, Person name Day -> Text -> Text -> Text -> Person

Person <$> areq textField "Name" Nothing
   :: AForm sub master (Day -> Text -> Text -> Text -> Person)

<*> -, Day, -, (Text -> Text -> Text -> Person), , -, Person. ( , -> , <$> <*> - , , $).

+12
source

All Articles