2013-09-24 4 views
7

Я просто изучаю Йесод/Хаскелл.Синтаксис Haskell: значение {..} и @

В следующем коде (http://www.yesodweb.com/book/restful-content) есть две вещи, которые я не понимаю (и следующий вопрос).

  1. {..} - Что это значит? (Это трудный термин для Google.)
  2. [email protected] - что делает знак @?
  3. Есть ли способ найти ответы на ungoglable синтаксис Haskell, не беспокоя вас всех на StackOverflow?

код:

{-# 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 
    [email protected] {..} = Person "Michael" 28 

main :: IO() 
main = warp 3000 App 

ответ

13

Для пунктов 1 и 2, я предполагаю, что вы имеете в виду линию

[email protected] {..} 

{..} происходит от расширения RecordWildcards. В основном он охватывает все поля типа данных Person. Вот почему вы можете использовать name и age в шаблоне Гамлета выше.

@ служит в качестве псевдонима. Каждый раз, когда вы видите [email protected]_expr, вы можете использовать id для всего значения, которое деконструировано по deconstructor_expr. Например, вы можете иметь

f (x:[email protected](y:_)) = a 

и a будет tail из списка аргументов, пока список содержит по крайней мере 2 элемента (т.е. f является tail для списков с более чем 2-х элементов).

Без этих двух, вся функция должна измениться к

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 

Заметим, что name и age являются функциями от записи к конкретному полю, и это означает, что вы должны использовать другие имена для значений (переменные-переменные '). Кроме того, поскольку мы больше не используем @, нам нужны отдельные строки для person и для полей.

Другой альтернативой было бы

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 

Вам все еще нужно вызвать name и age функции.

Для пункта 3 возможно перейти на IRC на #haskell и спросить там. Во всяком случае, те же люди оттуда здесь, это не беспокойство в вопросе.

+0

Итак, 'person @ Person {..} = Человек« Майкл »28' мог быть заменен на' name = «Michael» ',' age = 28' и 'person = Person name age'? – fadedbee

+0

Не совсем. Я обновил ответ, чтобы показать альтернативы. –

+0

Спасибо, я забыл, что 'name' и' age' - это имена функций 'Person', поэтому вам нужны новые идентификаторы. – fadedbee

2

{..} распаковывает запись в переменные. В вашем случае он определяет name и age. @ принимает все значение в соответствии с шаблоном, поэтому в [email protected] {..}, person будет оригинальным значением Person.

7

Добавление к другим ответам для поиска синтаксиса ungooglable symbolhound.com.

Смежные вопросы