I'm just learning Yesod/Haskell.
In the following code (http://www.yesodweb.com/book/restful-content) there are two things I don't understand (and a subsequent question).
{..}
- what does that mean? (It's a hard term to google for.)person@Person
- what does the @
sign do?code:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Text (Text)
import Yesod
data Person = Person
{ name :: Text
, age :: Int
}
instance ToJSON Person where
toJSON Person {..} = object
[ "name" .= name
, "age" .= age
]
data App = App
mkYesod "App" [parseRoutes|
/ HomeR GET
|]
instance Yesod App
getHomeR :: Handler TypedContent
getHomeR = selectRep $ do
provideRep $ return
[shamlet|
<p>Hello, my name is #{name} and I am #{age} years old.
|]
provideJson person
where
person@Person {..} = Person "Michael" 28
main :: IO ()
main = warp 3000 App
For points 1 and 2, I guess you're referring to line
person@Person {..}
The {..}
comes from the RecordWildcards
extension. Basically it brings in scope all fields of the Person
datatype. That's why you can use name
and age
in the Hamlet template above.
The @
serves as an alias. Everytime you see id@deconstructor_expr
you can use id
for the entire value which is deconstructed by deconstructor_expr
. For example you can have
f (x:a@(y:_)) = a
and a
will be the tail
of the argument list as long as the list has at least 2 elements (that is f
is tail
for lists with more than 2 elements).
Without these two, the entire function would have to change to
getHomeR :: Handler TypedContent
getHomeR = selectRep $ do
provideRep $ return
[shamlet|
<p>Hello, my name is #{name'} and I am #{age'} years old.
|]
provideJson person
where
person = Person "Michael" 28
name' = name person
age' = age person
Observe that name
and age
are functions from the record to the specific field and that means that you have to use other names for the values (the '
-ending variables). Also, because we no longer use @
we need separate lines for the person
and for the fields.
Another alternative would be
getHomeR :: Handler TypedContent
getHomeR = selectRep $ do
provideRep $ return
[shamlet|
<p>Hello, my name is #{name person} and I am #{age person} years old.
|]
provideJson person
where
person = Person "Michael" 28
You still need to call the name
and age
functions.
For point 3, a possibility is to go on IRC on #haskell and ask there. Anyway, the same people from there are here, it's not a bother in asking.
Adding to other answers, for searching for ungooglable syntax use symbolhound.com.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With